diff --git a/createallprojects.bat b/createallprojects.bat index 40c0f22..6fb35d3 100644 --- a/createallprojects.bat +++ b/createallprojects.bat @@ -1 +1,2 @@ -devtools\bin\vpc.exe /hl2mp +everything /mksln everything.sln +devtools\bin\vpc.exe /hl2mp +everything +coolsource /mksln everything.sln +pause \ No newline at end of file diff --git a/engine/console.cpp b/engine/console.cpp index ad9ba7a..816ea1e 100644 --- a/engine/console.cpp +++ b/engine/console.cpp @@ -1275,7 +1275,7 @@ void CConPanel::PaintBackground() int wide = GetWide(); char ver[ 100 ]; - Q_snprintf(ver, sizeof( ver ), "CoolSource Engine %i (%s)", PROTOCOL_VERSION, __TIMESTAMP__ ); + Q_snprintf(ver, sizeof( ver ), "CoolSource Engine %i (%s)", PROTOCOL_VERSION, __DATE__ ); wchar_t unicode[ 200 ]; g_pVGuiLocalize->ConvertANSIToUnicode( ver, unicode, sizeof( unicode ) ); diff --git a/launcher/RCa01748 b/launcher/RCa01748 new file mode 100644 index 0000000..68339f9 Binary files /dev/null and b/launcher/RCa01748 differ diff --git a/launcher/arrow.cur b/launcher/arrow.cur new file mode 100644 index 0000000..548b8da Binary files /dev/null and b/launcher/arrow.cur differ diff --git a/launcher/ifilesystem.h b/launcher/ifilesystem.h new file mode 100644 index 0000000..13c7047 --- /dev/null +++ b/launcher/ifilesystem.h @@ -0,0 +1,37 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Workfile: $ +// $Date: $ +// $NoKeywords: $ +//=============================================================================// +#ifndef IFILESYSTEM_H +#define IFILESYSTEM_H +#ifdef _WIN32 +#pragma once +#endif + +#include "interface.h" + + +class IFileSystem; + +//----------------------------------------------------------------------------- +// Loads, unloads the file system DLL +//----------------------------------------------------------------------------- +bool FileSystem_LoadFileSystemModule( void ); +void FileSystem_UnloadFileSystemModule( void ); + +CSysModule * FileSystem_LoadModule( const char* path ); +void FileSystem_UnloadModule( CSysModule *pModule ); + +bool FileSystem_Init( ); +void FileSystem_Shutdown( void ); + +// Sets the file system search path based on the game directory +bool FileSystem_SetGameDirectory( char const* pGameDir ); + +extern IFileSystem *g_pFileSystem; + +#endif // IFILESYSTEM_H \ No newline at end of file diff --git a/launcher/launcher.cpp b/launcher/launcher.cpp new file mode 100644 index 0000000..8593774 --- /dev/null +++ b/launcher/launcher.cpp @@ -0,0 +1,1321 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// Defines the entry point for the application. +// +//===========================================================================// + +#if defined( _WIN32 ) && !defined( _X360 ) +#include +#include "shlwapi.h" // registry stuff +#include +#elif defined ( LINUX ) || defined( OSX ) +#define O_EXLOCK 0 +#include +#include +#include +#include +#elif defined ( _X360 ) +#else +#error +#endif +#include "appframework/ilaunchermgr.h" +#include +#include "tier0/icommandline.h" +#include "engine_launcher_api.h" +#include "tier0/vcrmode.h" +#include "ifilesystem.h" +#include "tier1/interface.h" +#include "tier0/dbg.h" +#include "iregistry.h" +#include "appframework/IAppSystem.h" +#include "appframework/AppFramework.h" +#include +#include +#include "tier0/platform.h" +#include "tier0/memalloc.h" +#include "filesystem.h" +#include "tier1/utlrbtree.h" +#include "materialsystem/imaterialsystem.h" +#include "istudiorender.h" +#include "vgui/IVGui.h" +#include "IHammer.h" +#include "datacache/idatacache.h" +#include "datacache/imdlcache.h" +#include "vphysics_interface.h" +#include "filesystem_init.h" +#include "vstdlib/iprocessutils.h" +#include "video/ivideoservices.h" +#include "tier1/tier1.h" +#include "tier2/tier2.h" +#include "tier3/tier3.h" +#include "p4lib/ip4.h" +#include "inputsystem/iinputsystem.h" +#include "filesystem/IQueuedLoader.h" +#include "reslistgenerator.h" +#include "tier1/fmtstr.h" +#include "sourcevr/isourcevirtualreality.h" + +#define VERSION_SAFE_STEAM_API_INTERFACES +#include "steam/steam_api.h" + +#if defined( USE_SDL ) +#include "SDL.h" + +#if !defined( _WIN32 ) +#define MB_OK 0x00000001 +#define MB_SYSTEMMODAL 0x00000002 +#define MB_ICONERROR 0x00000004 +int MessageBox(HWND hWnd, const char* message, const char* header, unsigned uType); +#endif // _WIN32 + +#endif // USE_SDL + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#define DEFAULT_HL2_GAMEDIR "hl2" + +#if defined( USE_SDL ) +extern void* CreateSDLMgr(); +#endif + +//----------------------------------------------------------------------------- +// Modules... +//----------------------------------------------------------------------------- +static IEngineAPI* g_pEngineAPI; +static IHammer* g_pHammer; + +bool g_bTextMode = false; + +static char g_szBasedir[MAX_PATH]; +static char g_szGamedir[MAX_PATH]; + +// copied from sys.h +struct FileAssociationInfo +{ + char const* extension; + char const* command_to_issue; +}; + +static FileAssociationInfo g_FileAssociations[] = +{ + { ".dem", "playdemo" }, + { ".sav", "load" }, + { ".bsp", "map" }, +}; + +#ifdef _WIN32 +#pragma warning(disable:4073) +#pragma init_seg(lib) +#endif + +class CLeakDump +{ +public: + CLeakDump() + : m_bCheckLeaks(false) + { + } + + ~CLeakDump() + { + if (m_bCheckLeaks) + { + MemAlloc_DumpStats(); + } + } + + bool m_bCheckLeaks; +} g_LeakDump; + +//----------------------------------------------------------------------------- +// Spew function! +//----------------------------------------------------------------------------- +SpewRetval_t LauncherDefaultSpewFunc(SpewType_t spewType, char const* pMsg) +{ +#ifndef _CERT +#ifdef WIN32 + OutputDebugStringA(pMsg); +#endif + + switch (spewType) + { + case SPEW_MESSAGE: + case SPEW_LOG: + return SPEW_CONTINUE; + + case SPEW_WARNING: + if (!stricmp(GetSpewOutputGroup(), "init")) + { +#if defined( WIN32 ) || defined( USE_SDL ) + ::MessageBox(NULL, pMsg, "Warning!", MB_OK | MB_SYSTEMMODAL | MB_ICONERROR); +#endif + } + return SPEW_CONTINUE; + + case SPEW_ASSERT: + if (!ShouldUseNewAssertDialog()) + { +#if defined( WIN32 ) || defined( USE_SDL ) + ::MessageBox(NULL, pMsg, "Assert!", MB_OK | MB_SYSTEMMODAL | MB_ICONERROR); +#endif + } + return SPEW_DEBUGGER; + + case SPEW_ERROR: + default: +#if defined( WIN32 ) || defined( USE_SDL ) + ::MessageBox(NULL, pMsg, "Error!", MB_OK | MB_SYSTEMMODAL | MB_ICONERROR); +#endif + _exit(1); + } +#endif +} + + +//----------------------------------------------------------------------------- +// Implementation of VCRHelpers. +//----------------------------------------------------------------------------- +class CVCRHelpers : public IVCRHelpers +{ +public: + virtual void ErrorMessage(const char* pMsg) + { +#if defined( WIN32 ) || defined( LINUX ) + NOVCR(::MessageBox(NULL, pMsg, "VCR Error", MB_OK)); +#endif + } + + virtual void* GetMainWindow() + { + return NULL; + } +}; + +static CVCRHelpers g_VCRHelpers; + +//----------------------------------------------------------------------------- +// Purpose: Return the game directory +// Output : char +//----------------------------------------------------------------------------- +char* GetGameDirectory(void) +{ + return g_szGamedir; +} + +void SetGameDirectory(const char* game) +{ + Q_strncpy(g_szGamedir, game, sizeof(g_szGamedir)); +} + +//----------------------------------------------------------------------------- +// Gets the executable name +//----------------------------------------------------------------------------- +bool GetExecutableName(char* out, int outSize) +{ +#ifdef WIN32 + if (!::GetModuleFileName((HINSTANCE)GetModuleHandle(NULL), out, outSize)) + { + return false; + } + return true; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: Return the base directory +// Output : char +//----------------------------------------------------------------------------- +char* GetBaseDirectory(void) +{ + return g_szBasedir; +} + +//----------------------------------------------------------------------------- +// Purpose: Determine the directory where this .exe is running from +//----------------------------------------------------------------------------- +void UTIL_ComputeBaseDir() +{ + g_szBasedir[0] = 0; + + if (IsX360()) + { + char const* pBaseDir = CommandLine()->ParmValue("-basedir"); + if (pBaseDir) + { + strcpy(g_szBasedir, pBaseDir); + } + } + + if (!g_szBasedir[0] && GetExecutableName(g_szBasedir, sizeof(g_szBasedir))) + { + char* pBuffer = strrchr(g_szBasedir, '\\'); + if (*pBuffer) + { + *(pBuffer + 1) = '\0'; + } + + int j = strlen(g_szBasedir); + if (j > 0) + { + if ((g_szBasedir[j - 1] == '\\') || + (g_szBasedir[j - 1] == '/')) + { + g_szBasedir[j - 1] = 0; + } + } + } + + if (IsPC()) + { + char const* pOverrideDir = CommandLine()->CheckParm("-basedir"); + if (pOverrideDir) + { + strcpy(g_szBasedir, pOverrideDir); + } + } + +#ifdef WIN32 + Q_strlower(g_szBasedir); +#endif + Q_FixSlashes(g_szBasedir); +} + +#ifdef WIN32 +BOOL WINAPI MyHandlerRoutine(DWORD dwCtrlType) +{ +#if !defined( _X360 ) + TerminateProcess(GetCurrentProcess(), 2); +#endif + return TRUE; +} +#endif + +void InitTextMode() +{ +#ifdef WIN32 + AllocConsole(); + + SetConsoleCtrlHandler(MyHandlerRoutine, TRUE); + + freopen("CONIN$", "rb", stdin); // reopen stdin handle as console window input + freopen("CONOUT$", "wb", stdout); // reopen stout handle as console window output + freopen("CONOUT$", "wb", stderr); // reopen stderr handle as console window output +#endif +} + +void SortResList(char const* pchFileName, char const* pchSearchPath); + +#define ALL_RESLIST_FILE "all.lst" +#define ENGINE_RESLIST_FILE "engine.lst" + +// create file to dump out to +class CLogAllFiles +{ +public: + CLogAllFiles(); + void Init(); + void Shutdown(); + void LogFile(const char* fullPathFileName, const char* options); + +private: + static void LogAllFilesFunc(const char* fullPathFileName, const char* options); + void LogToAllReslist(char const* line); + + bool m_bActive; + char m_szCurrentDir[_MAX_PATH]; + + // persistent across restarts + CUtlRBTree< CUtlString, int > m_Logged; + CUtlString m_sResListDir; + CUtlString m_sFullGamePath; +}; + +static CLogAllFiles g_LogFiles; + +static bool AllLogLessFunc(CUtlString const& pLHS, CUtlString const& pRHS) +{ + return CaselessStringLessThan(pLHS.Get(), pRHS.Get()); +} + +CLogAllFiles::CLogAllFiles() : + m_bActive(false), + m_Logged(0, 0, AllLogLessFunc) +{ + MEM_ALLOC_CREDIT(); + m_sResListDir = "reslists"; +} + +void CLogAllFiles::Init() +{ + if (IsX360()) + { + return; + } + + // Can't do this in edit mode + if (CommandLine()->CheckParm("-edit")) + { + return; + } + + if (!CommandLine()->CheckParm("-makereslists")) + { + return; + } + + m_bActive = true; + + char const* pszDir = NULL; + if (CommandLine()->CheckParm("-reslistdir", &pszDir) && pszDir) + { + char szDir[MAX_PATH]; + Q_strncpy(szDir, pszDir, sizeof(szDir)); + Q_StripTrailingSlash(szDir); +#ifdef WIN32 + Q_strlower(szDir); +#endif + Q_FixSlashes(szDir); + if (Q_strlen(szDir) > 0) + { + m_sResListDir = szDir; + } + } + + // game directory has not been established yet, must derive ourselves + char path[MAX_PATH]; + Q_snprintf(path, sizeof(path), "%s/%s", GetBaseDirectory(), CommandLine()->ParmValue("-game", "hl2")); + Q_FixSlashes(path); +#ifdef WIN32 + Q_strlower(path); +#endif + m_sFullGamePath = path; + + // create file to dump out to + char szDir[MAX_PATH]; + V_snprintf(szDir, sizeof(szDir), "%s\\%s", m_sFullGamePath.String(), m_sResListDir.String()); + g_pFullFileSystem->CreateDirHierarchy(szDir, "GAME"); + + g_pFullFileSystem->AddLoggingFunc(&LogAllFilesFunc); + + if (!CommandLine()->FindParm("-startmap") && !CommandLine()->FindParm("-startstage")) + { + m_Logged.RemoveAll(); + g_pFullFileSystem->RemoveFile(CFmtStr("%s\\%s\\%s", m_sFullGamePath.String(), m_sResListDir.String(), ALL_RESLIST_FILE), "GAME"); + } + +#ifdef WIN32 + ::GetCurrentDirectory(sizeof(m_szCurrentDir), m_szCurrentDir); + Q_strncat(m_szCurrentDir, "\\", sizeof(m_szCurrentDir), 1); + _strlwr(m_szCurrentDir); +#endif +} + +void CLogAllFiles::Shutdown() +{ + if (!m_bActive) + return; + + m_bActive = false; + + if (CommandLine()->CheckParm("-makereslists")) + { + g_pFullFileSystem->RemoveLoggingFunc(&LogAllFilesFunc); + } + + // Now load and sort all.lst + SortResList(CFmtStr("%s\\%s\\%s", m_sFullGamePath.String(), m_sResListDir.String(), ALL_RESLIST_FILE), "GAME"); + // Now load and sort engine.lst + SortResList(CFmtStr("%s\\%s\\%s", m_sFullGamePath.String(), m_sResListDir.String(), ENGINE_RESLIST_FILE), "GAME"); + + m_Logged.Purge(); +} + +void CLogAllFiles::LogToAllReslist(char const* line) +{ + // Open for append, write data, close. + FileHandle_t fh = g_pFullFileSystem->Open(CFmtStr("%s\\%s\\%s", m_sFullGamePath.String(), m_sResListDir.String(), ALL_RESLIST_FILE), "at", "GAME"); + if (fh != FILESYSTEM_INVALID_HANDLE) + { + g_pFullFileSystem->Write("\"", 1, fh); + g_pFullFileSystem->Write(line, Q_strlen(line), fh); + g_pFullFileSystem->Write("\"\n", 2, fh); + g_pFullFileSystem->Close(fh); + } +} + +void CLogAllFiles::LogFile(const char* fullPathFileName, const char* options) +{ + if (!m_bActive) + { + Assert(0); + return; + } + + // write out to log file + Assert(fullPathFileName[1] == ':'); + + int idx = m_Logged.Find(fullPathFileName); + if (idx != m_Logged.InvalidIndex()) + { + return; + } + + m_Logged.Insert(fullPathFileName); + + // make it relative to our root directory + const char* relative = Q_stristr(fullPathFileName, GetBaseDirectory()); + if (relative) + { + relative += (Q_strlen(GetBaseDirectory()) + 1); + + char rel[MAX_PATH]; + Q_strncpy(rel, relative, sizeof(rel)); +#ifdef WIN32 + Q_strlower(rel); +#endif + Q_FixSlashes(rel); + + LogToAllReslist(rel); + } +} + +//----------------------------------------------------------------------------- +// Purpose: callback function from filesystem +//----------------------------------------------------------------------------- +void CLogAllFiles::LogAllFilesFunc(const char* fullPathFileName, const char* options) +{ + g_LogFiles.LogFile(fullPathFileName, options); +} + +//----------------------------------------------------------------------------- +// Purpose: This is a bit of a hack because it appears +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +static bool IsWin98OrOlder() +{ + bool retval = false; + +#if defined( WIN32 ) && !defined( _X360 ) + OSVERSIONINFOEX osvi; + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + + BOOL bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO*)&osvi); + if (!bOsVersionInfoEx) + { + // If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO. + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if (!GetVersionEx((OSVERSIONINFO*)&osvi)) + { + Error("IsWin98OrOlder: Unable to get OS version information"); + } + } + + switch (osvi.dwPlatformId) + { + case VER_PLATFORM_WIN32_NT: + // NT, XP, Win2K, etc. all OK for SSE + break; + case VER_PLATFORM_WIN32_WINDOWS: + // Win95, 98, Me can't do SSE + retval = true; + break; + case VER_PLATFORM_WIN32s: + // Can't really run this way I don't think... + retval = true; + break; + default: + break; + } +#endif + + return retval; +} + + +//----------------------------------------------------------------------------- +// Purpose: Figure out if Steam is running, then load the GameOverlayRenderer.dll +//----------------------------------------------------------------------------- +void TryToLoadSteamOverlayDLL() +{ +#if defined( WIN32 ) && !defined( _X360 ) + // First, check if the module is already loaded, perhaps because we were run from Steam directly + HMODULE hMod = GetModuleHandle("GameOverlayRenderer" DLL_EXT_STRING); + if (hMod) + { + return; + } + + if (0 == GetEnvironmentVariableA("SteamGameId", NULL, 0)) + { + // Initializing the Steam client API has the side effect of setting up the AppId + // which is immediately queried in GameOverlayRenderer.dll's DllMain entry point + if (SteamAPI_InitSafe()) + { + const char* pchSteamInstallPath = SteamAPI_GetSteamInstallPath(); + if (pchSteamInstallPath) + { + char rgchSteamPath[MAX_PATH]; + V_ComposeFileName(pchSteamInstallPath, "GameOverlayRenderer" DLL_EXT_STRING, rgchSteamPath, Q_ARRAYSIZE(rgchSteamPath)); + // This could fail, but we can't fix it if it does so just ignore failures + LoadLibrary(rgchSteamPath); + + } + + SteamAPI_Shutdown(); + } + } + +#endif +} + +//----------------------------------------------------------------------------- +// Inner loop: initialize, shutdown main systems, load steam to +//----------------------------------------------------------------------------- +class CSourceAppSystemGroup : public CSteamAppSystemGroup +{ +public: + // Methods of IApplication + virtual bool Create(); + virtual bool PreInit(); + virtual int Main(); + virtual void PostShutdown(); + virtual void Destroy(); + +private: + const char* DetermineDefaultMod(); + const char* DetermineDefaultGame(); + + bool m_bEditMode; +}; + + +//----------------------------------------------------------------------------- +// The dirty disk error report function +//----------------------------------------------------------------------------- +void ReportDirtyDiskNoMaterialSystem() +{ + // removed +} + + +//----------------------------------------------------------------------------- +// Instantiate all main libraries +//----------------------------------------------------------------------------- +bool CSourceAppSystemGroup::Create() +{ + IFileSystem* pFileSystem = (IFileSystem*)FindSystem(FILESYSTEM_INTERFACE_VERSION); + pFileSystem->InstallDirtyDiskReportFunc(ReportDirtyDiskNoMaterialSystem); + +#ifdef WIN32 + CoInitialize(NULL); +#endif + + // Are we running in edit mode? + m_bEditMode = CommandLine()->CheckParm("-edit"); + + double st = Plat_FloatTime(); + + AppSystemInfo_t appSystems[] = + { + { "engine" DLL_EXT_STRING, CVAR_QUERY_INTERFACE_VERSION }, // NOTE: This one must be first!! + { "inputsystem" DLL_EXT_STRING, INPUTSYSTEM_INTERFACE_VERSION }, + { "filesystem_stdio" DLL_EXT_STRING, FILESYSTEM_INTERFACE_VERSION }, + { "materialsystem" DLL_EXT_STRING, MATERIAL_SYSTEM_INTERFACE_VERSION }, + { "datacache" DLL_EXT_STRING, DATACACHE_INTERFACE_VERSION }, + { "datacache" DLL_EXT_STRING, MDLCACHE_INTERFACE_VERSION }, + { "datacache" DLL_EXT_STRING, STUDIO_DATA_CACHE_INTERFACE_VERSION }, + { "studiorender" DLL_EXT_STRING, STUDIO_RENDER_INTERFACE_VERSION }, + { "vphysics" DLL_EXT_STRING, VPHYSICS_INTERFACE_VERSION }, + { "video_services" DLL_EXT_STRING, VIDEO_SERVICES_INTERFACE_VERSION }, + + // NOTE: This has to occur before vgui2.dll so it replaces vgui2's surface implementation + { "vguimatsurface" DLL_EXT_STRING, VGUI_SURFACE_INTERFACE_VERSION }, + { "vgui2" DLL_EXT_STRING, VGUI_IVGUI_INTERFACE_VERSION }, + { "engine" DLL_EXT_STRING, VENGINE_LAUNCHER_API_VERSION }, + + { "", "" } // Required to terminate the list + }; + +#if defined( USE_SDL ) + AddSystem((IAppSystem*)CreateSDLMgr(), SDLMGR_INTERFACE_VERSION); +#endif + + if (!AddSystems(appSystems)) + return false; + + + // This will be NULL for games that don't support VR. That's ok. Just don't load the DLL + AppModule_t sourceVRModule = LoadModule("sourcevr" DLL_EXT_STRING); + if (sourceVRModule != APP_MODULE_INVALID) + { + AddSystem(sourceVRModule, SOURCE_VIRTUAL_REALITY_INTERFACE_VERSION); + } + + // pull in our filesystem dll to pull the queued loader from it, we need to do it this way due to the + // steam/stdio split for our steam filesystem + char pFileSystemDLL[MAX_PATH]; + bool bSteam; + if (FileSystem_GetFileSystemDLLName(pFileSystemDLL, MAX_PATH, bSteam) != FS_OK) + return false; + + AppModule_t fileSystemModule = LoadModule(pFileSystemDLL); + AddSystem(fileSystemModule, QUEUEDLOADER_INTERFACE_VERSION); + + // Hook in datamodel and p4 control if we're running with -tools + if (IsPC() && ((CommandLine()->FindParm("-tools") && !CommandLine()->FindParm("-nop4")) || CommandLine()->FindParm("-p4"))) + { +#ifdef STAGING_ONLY + AppModule_t p4libModule = LoadModule("p4lib" DLL_EXT_STRING); + IP4* p4 = (IP4*)AddSystem(p4libModule, P4_INTERFACE_VERSION); + + // If we are running with -steam then that means the tools are being used by an SDK user. Don't exit in this case! + if (!p4 && !CommandLine()->FindParm("-steam")) + { + return false; + } +#endif // STAGING_ONLY + + AppModule_t vstdlibModule = LoadModule("vstdlib" DLL_EXT_STRING); + IProcessUtils* processUtils = (IProcessUtils*)AddSystem(vstdlibModule, PROCESS_UTILS_INTERFACE_VERSION); + if (!processUtils) + return false; + } + + // Connect to iterfaces loaded in AddSystems that we need locally + IMaterialSystem* pMaterialSystem = (IMaterialSystem*)FindSystem(MATERIAL_SYSTEM_INTERFACE_VERSION); + if (!pMaterialSystem) + return false; + + g_pEngineAPI = (IEngineAPI*)FindSystem(VENGINE_LAUNCHER_API_VERSION); + + // Load the hammer DLL if we're in editor mode +#if defined( _WIN32 ) && defined( STAGING_ONLY ) + if (m_bEditMode) + { + AppModule_t hammerModule = LoadModule("hammer_dll" DLL_EXT_STRING); + g_pHammer = (IHammer*)AddSystem(hammerModule, INTERFACEVERSION_HAMMER); + if (!g_pHammer) + { + return false; + } + } +#endif // defined( _WIN32 ) && defined( STAGING_ONLY ) + + // Load up the appropriate shader DLL + // This has to be done before connection. + char const* pDLLName = "shaderapidx9" DLL_EXT_STRING; + if (CommandLine()->FindParm("-noshaderapi")) + { + pDLLName = "shaderapiempty" DLL_EXT_STRING; + } + + pMaterialSystem->SetShaderAPI(pDLLName); + + double elapsed = Plat_FloatTime() - st; + COM_TimestampedLog("LoadAppSystems: Took %.4f secs to load libraries and get factories.", (float)elapsed); + + return true; +} + +bool CSourceAppSystemGroup::PreInit() +{ + CreateInterfaceFn factory = GetFactory(); + ConnectTier1Libraries(&factory, 1); + ConVar_Register(); + ConnectTier2Libraries(&factory, 1); + ConnectTier3Libraries(&factory, 1); + + if (!g_pFullFileSystem || !g_pMaterialSystem) + return false; + + CFSSteamSetupInfo steamInfo; + steamInfo.m_bToolsMode = false; + steamInfo.m_bSetSteamDLLPath = false; + steamInfo.m_bSteam = g_pFullFileSystem->IsSteam(); + steamInfo.m_bOnlyUseDirectoryName = true; + steamInfo.m_pDirectoryName = DetermineDefaultMod(); + if (!steamInfo.m_pDirectoryName) + { + steamInfo.m_pDirectoryName = DetermineDefaultGame(); + if (!steamInfo.m_pDirectoryName) + { + Error("FileSystem_LoadFileSystemModule: no -defaultgamedir or -game specified."); + } + } + if (FileSystem_SetupSteamEnvironment(steamInfo) != FS_OK) + return false; + + CFSMountContentInfo fsInfo; + fsInfo.m_pFileSystem = g_pFullFileSystem; + fsInfo.m_bToolsMode = m_bEditMode; + fsInfo.m_pDirectoryName = steamInfo.m_GameInfoPath; + if (FileSystem_MountContent(fsInfo) != FS_OK) + return false; + + if (IsPC() || !IsX360()) + { + fsInfo.m_pFileSystem->AddSearchPath("platform", "PLATFORM"); + } + else + { + // 360 needs absolute paths + FileSystem_AddSearchPath_Platform(g_pFullFileSystem, steamInfo.m_GameInfoPath); + } + + if (IsPC()) + { + // This will get called multiple times due to being here, but only the first one will do anything + reslistgenerator->Init(GetBaseDirectory(), CommandLine()->ParmValue("-game", "hl2")); + + // This will also get called each time, but will actually fix up the command line as needed + reslistgenerator->SetupCommandLine(); + } + + // FIXME: Logfiles is mod-specific, needs to move into the engine. + g_LogFiles.Init(); + + // Required to run through the editor + if (m_bEditMode) + { + g_pMaterialSystem->EnableEditorMaterials(); + } + + StartupInfo_t info; + info.m_pInstance = GetAppInstance(); + info.m_pBaseDirectory = GetBaseDirectory(); + info.m_pInitialMod = DetermineDefaultMod(); + info.m_pInitialGame = DetermineDefaultGame(); + info.m_pParentAppSystemGroup = this; + info.m_bTextMode = g_bTextMode; + + g_pEngineAPI->SetStartupInfo(info); + + return true; +} + +int CSourceAppSystemGroup::Main() +{ + return g_pEngineAPI->Run(); +} + +void CSourceAppSystemGroup::PostShutdown() +{ + // FIXME: Logfiles is mod-specific, needs to move into the engine. + g_LogFiles.Shutdown(); + + reslistgenerator->Shutdown(); + + DisconnectTier3Libraries(); + DisconnectTier2Libraries(); + ConVar_Unregister(); + DisconnectTier1Libraries(); +} + +void CSourceAppSystemGroup::Destroy() +{ + g_pEngineAPI = NULL; + g_pMaterialSystem = NULL; + g_pHammer = NULL; + +#ifdef WIN32 + CoUninitialize(); +#endif +} + + +//----------------------------------------------------------------------------- +// Determines the initial mod to use at load time. +// We eventually (hopefully) will be able to switch mods at runtime +// because the engine/hammer integration really wants this feature. +//----------------------------------------------------------------------------- +const char* CSourceAppSystemGroup::DetermineDefaultMod() +{ + if (!m_bEditMode) + { + return CommandLine()->ParmValue("-game", DEFAULT_HL2_GAMEDIR); + } + return g_pHammer->GetDefaultMod(); +} + +const char* CSourceAppSystemGroup::DetermineDefaultGame() +{ + if (!m_bEditMode) + { + return CommandLine()->ParmValue("-defaultgamedir", DEFAULT_HL2_GAMEDIR); + } + return g_pHammer->GetDefaultGame(); +} + +//----------------------------------------------------------------------------- +// MessageBox for SDL/OSX +//----------------------------------------------------------------------------- +#if defined( USE_SDL ) && !defined( _WIN32 ) + +int MessageBox(HWND hWnd, const char* message, const char* header, unsigned uType) +{ + SDL_ShowSimpleMessageBox(0, header, message, GetAssertDialogParent()); + return 0; +} + +#endif + +//----------------------------------------------------------------------------- +// Allow only one windowed source app to run at a time +//----------------------------------------------------------------------------- +#ifdef WIN32 +HANDLE g_hMutex = NULL; +#endif +bool GrabSourceMutex() +{ +#ifdef WIN32 + if (IsPC()) + { + // don't allow more than one instance to run + g_hMutex = ::CreateMutex(NULL, FALSE, TEXT("hl2_singleton_mutex")); + + unsigned int waitResult = ::WaitForSingleObject(g_hMutex, 0); + + // Here, we have the mutex + if (waitResult == WAIT_OBJECT_0 || waitResult == WAIT_ABANDONED) + return true; + + // couldn't get the mutex, we must be running another instance + ::CloseHandle(g_hMutex); + + return false; + } +#endif + return true; +} + +void ReleaseSourceMutex() +{ +#ifdef WIN32 + if (IsPC() && g_hMutex) + { + ::ReleaseMutex(g_hMutex); + ::CloseHandle(g_hMutex); + g_hMutex = NULL; + } +#elif defined(POSIX) + if (g_lockfd != -1) + { + close(g_lockfd); + g_lockfd = -1; + unlink(g_lockFilename); + } +#endif +} + +// Remove all but the last -game parameter. +// This is for mods based off something other than Half-Life 2 (like HL2MP mods). +// The Steam UI does 'steam -applaunch 320 -game c:\steam\steamapps\sourcemods\modname', but applaunch inserts +// its own -game parameter, which would supercede the one we really want if we didn't intercede here. +void RemoveSpuriousGameParameters() +{ + // Find the last -game parameter. + int nGameArgs = 0; + char lastGameArg[MAX_PATH]; + for (int i = 0; i < CommandLine()->ParmCount() - 1; i++) + { + if (Q_stricmp(CommandLine()->GetParm(i), "-game") == 0) + { + Q_snprintf(lastGameArg, sizeof(lastGameArg), "\"%s\"", CommandLine()->GetParm(i + 1)); + ++nGameArgs; + ++i; + } + } + + // We only care if > 1 was specified. + if (nGameArgs > 1) + { + CommandLine()->RemoveParm("-game"); + CommandLine()->AppendParm("-game", lastGameArg); + } +} + +/* +============ +va + +does a varargs printf into a temp buffer, so I don't need to have +varargs versions of all text functions. +============ +*/ +static char* va(char* format, ...) +{ + va_list argptr; + static char string[8][512]; + static int curstring = 0; + + curstring = (curstring + 1) % 8; + + va_start(argptr, format); + Q_vsnprintf(string[curstring], sizeof(string[curstring]), format, argptr); + va_end(argptr); + + return string[curstring]; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *param - +// Output : static char const +//----------------------------------------------------------------------------- +static char const* Cmd_TranslateFileAssociation(char const* param) +{ + static char sz[512]; + char* retval = NULL; + + char temp[512]; + Q_strncpy(temp, param, sizeof(temp)); + Q_FixSlashes(temp); +#ifdef WIN32 + Q_strlower(temp); +#endif + const char* extension = V_GetFileExtension(temp); + // must have an extension to map + if (!extension) + return retval; + extension--; // back up so we have the . in the extension + + int c = ARRAYSIZE(g_FileAssociations); + for (int i = 0; i < c; i++) + { + FileAssociationInfo& info = g_FileAssociations[i]; + + if (!Q_strcmp(extension, info.extension) && + !CommandLine()->FindParm(va("+%s", info.command_to_issue))) + { + // Translate if haven't already got one of these commands + Q_strncpy(sz, temp, sizeof(sz)); + Q_FileBase(sz, temp, sizeof(sz)); + + Q_snprintf(sz, sizeof(sz), "%s %s", info.command_to_issue, temp); + retval = sz; + break; + } + } + + // return null if no translation, otherwise return commands + return retval; +} + +//----------------------------------------------------------------------------- +// Purpose: Converts all the convar args into a convar command +// Input : none +// Output : const char * series of convars +//----------------------------------------------------------------------------- +static const char* BuildCommand() +{ + static CUtlBuffer build(0, 0, CUtlBuffer::TEXT_BUFFER); + build.Clear(); + + // arg[0] is the executable name + for (int i = 1; i < CommandLine()->ParmCount(); i++) + { + const char* szParm = CommandLine()->GetParm(i); + if (!szParm) continue; + + if (szParm[0] == '-') + { + // skip -XXX options and eat their args + const char* szValue = CommandLine()->ParmValue(szParm); + if (szValue) i++; + continue; + } + if (szParm[0] == '+') + { + // convert +XXX options and stuff them into the build buffer + const char* szValue = CommandLine()->ParmValue(szParm); + if (szValue) + { + build.PutString(va("%s %s;", szParm + 1, szValue)); + i++; + } + else + { + build.PutString(szParm + 1); + build.PutChar(';'); + } + } + else + { + // singleton values, convert to command + char const* translated = Cmd_TranslateFileAssociation(CommandLine()->GetParm(i)); + if (translated) + { + build.PutString(translated); + build.PutChar(';'); + } + } + } + + build.PutChar('\0'); + + return (const char*)build.Base(); +} + + + +//----------------------------------------------------------------------------- +// Purpose: The real entry point for the application +// Input : hInstance - +// hPrevInstance - +// lpCmdLine - +// nCmdShow - +// Output : int APIENTRY +//----------------------------------------------------------------------------- +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) +{ +#ifdef WIN32 + SetAppInstance(hInstance); +#endif + + // Hook the debug output stuff. + SpewOutputFunc(LauncherDefaultSpewFunc); + + if (0 && IsWin98OrOlder()) + { + Error("This build does not currently run under Windows 98/Me."); + return -1; + } + + // Quickly check the hardware key, essentially a warning shot. + if (!Plat_VerifyHardwareKeyPrompt()) + { + return -1; + } + + const char* filename; + + CommandLine()->CreateCmdLine(IsPC() ? VCRHook_GetCommandLine() : lpCmdLine); + + // If we're using -default command line parameters, get rid of DX8 settings. + if (CommandLine()->CheckParm("-default")) + { + CommandLine()->RemoveParm("-dxlevel"); + CommandLine()->RemoveParm("-maxdxlevel"); + CommandLine()->RemoveParm("+mat_dxlevel"); + } + + // Figure out the directory the executable is running from + UTIL_ComputeBaseDir(); + + // This call is to emulate steam's injection of the GameOverlay DLL into our process if we + // are running from the command line directly, this allows the same experience the user gets + // to be present when running from perforce, the call has no effect on X360 + TryToLoadSteamOverlayDLL(); + + // Start VCR mode? + if (CommandLine()->CheckParm("-vcrrecord", &filename)) + { + if (!VCRStart(filename, true, &g_VCRHelpers)) + { + Error("-vcrrecord: can't open '%s' for writing.\n", filename); + return -1; + } + } + else if (CommandLine()->CheckParm("-vcrplayback", &filename)) + { + if (!VCRStart(filename, false, &g_VCRHelpers)) + { + Error("-vcrplayback: can't open '%s' for reading.\n", filename); + return -1; + } + } + + // See the function for why we do this. + RemoveSpuriousGameParameters(); + +#ifdef WIN32 + if (IsPC()) + { + // initialize winsock + WSAData wsaData; + int nError = ::WSAStartup(MAKEWORD(2, 0), &wsaData); + if (nError) + { + Msg("Warning! Failed to start Winsock via WSAStartup = 0x%x.\n", nError); + } + } +#endif + + // Run in text mode? (No graphics or sound). + // NOTE: Currently crashing the game, will look into later. + //if (CommandLine()->CheckParm("-textmode")) + //{ + // g_bTextMode = true; + // InitTextMode(); + //} +#ifdef WIN32 + else + { + int retval = -1; + // Can only run one windowed source app at a time + if (!GrabSourceMutex()) + { + // Allow the user to explicitly say they want to be able to run multiple instances of the source mutex. + // Useful for side-by-side comparisons of different renderers. + bool multiRun = CommandLine()->CheckParm("-multirun") != NULL; + + // We're going to hijack the existing session and load a new savegame into it. This will mainly occur when users click on links in Bugzilla that will automatically copy saves and load them + // directly from the web browser. The -hijack command prevents the launcher from objecting that there is already an instance of the game. + if (CommandLine()->CheckParm("-hijack")) + { + HWND hwndEngine = FindWindow("Valve001", NULL); + + // Can't find the engine + if (hwndEngine == NULL) + { + ::MessageBox(NULL, "The modified entity keyvalues could not be sent to the Source Engine because the engine does not appear to be running.", "Source Engine Not Running", MB_OK | MB_ICONEXCLAMATION); + } + else + { + const char* szCommand = BuildCommand(); + + // + // Fill out the data structure to send to the engine. + // + COPYDATASTRUCT copyData; + copyData.cbData = strlen(szCommand) + 1; + copyData.dwData = 0; + copyData.lpData = (void*)szCommand; + + if (!::SendMessage(hwndEngine, WM_COPYDATA, 0, (LPARAM)©Data)) + { + ::MessageBox(NULL, "The Source Engine was found running, but did not accept the request to load a savegame. It may be an old version of the engine that does not support this functionality.", "Source Engine Declined Request", MB_OK | MB_ICONEXCLAMATION); + } + else + { + retval = 0; + } + + free((void*)szCommand); + } + } + else + { + if (!multiRun) { + ::MessageBox(NULL, "Only one instance of the game can be running at one time.", "Source - Warning", MB_ICONINFORMATION | MB_OK); + } + } + + if (!multiRun) { + return retval; + } + } + } +#endif + +#ifdef WIN32 + // Make low priority? + // NOTE: This currently is causing a crash. Will look into this later. + /* + if (CommandLine()->CheckParm("-low")) + { + SetPriorityClass(GetCurrentProcess(), IDLE_PRIORITY_CLASS); + } + else if (CommandLine()->CheckParm("-high")) + { + SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); + } + */ +#endif + + // If game is not run from Steam then add -insecure in order to avoid client timeout message + if (CommandLine()->CheckParm("-steam") == NULL) + { + CommandLine()->AppendParm("-insecure", NULL); + } + + // Figure out the directory the executable is running from + // and make that be the current working directory + _chdir(GetBaseDirectory()); + + g_LeakDump.m_bCheckLeaks = CommandLine()->CheckParm("-leakcheck") ? true : false; + + bool bRestart = true; + while (bRestart) + { + bRestart = false; + + CSourceAppSystemGroup sourceSystems; + CSteamApplication steamApplication(&sourceSystems); + int nRetval = steamApplication.Run(); + if (steamApplication.GetErrorStage() == CSourceAppSystemGroup::INITIALIZATION) + { + bRestart = (nRetval == INIT_RESTART); + } + else if (nRetval == RUN_RESTART) + { + bRestart = true; + } + + bool bReslistCycle = false; + if (!bRestart) + { + bReslistCycle = reslistgenerator->ShouldContinue(); + bRestart = bReslistCycle; + } + + if (!bReslistCycle) + { + // Remove any overrides in case settings changed + // NOTE: This, sadly, is also causing a crash. Will look into, later. + /* + CommandLine()->RemoveParm("-w"); + CommandLine()->RemoveParm("-h"); + CommandLine()->RemoveParm("-width"); + CommandLine()->RemoveParm("-height"); + CommandLine()->RemoveParm("-sw"); + CommandLine()->RemoveParm("-startwindowed"); + CommandLine()->RemoveParm("-windowed"); + CommandLine()->RemoveParm("-window"); + CommandLine()->RemoveParm("-full"); + CommandLine()->RemoveParm("-fullscreen"); + CommandLine()->RemoveParm("-dxlevel"); + CommandLine()->RemoveParm("-autoconfig"); + CommandLine()->RemoveParm("+mat_hdr_level"); + */ + } + } + +#ifdef WIN32 + if (IsPC()) + { + // shutdown winsock + int nError = ::WSACleanup(); + if (nError) + { + Msg("Warning! Failed to complete WSACleanup = 0x%x.\n", nError); + } + } +#endif + + // Allow other source apps to run + ReleaseSourceMutex(); + + // Now that the mutex has been released, check HKEY_CURRENT_USER\Software\Valve\Source\Relaunch URL. If there is a URL here, exec it. + // This supports the capability of immediately re-launching the the game via Steam in a different audio language + HKEY hKey; + if (RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Valve\\Source", NULL, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS) + { + char szValue[MAX_PATH]; + DWORD dwValueLen = MAX_PATH; + + if (RegQueryValueEx(hKey, "Relaunch URL", NULL, NULL, (unsigned char*)szValue, &dwValueLen) == ERROR_SUCCESS) + { + ShellExecute(0, "open", szValue, 0, 0, SW_SHOW); + RegDeleteValue(hKey, "Relaunch URL"); + } + + RegCloseKey(hKey); + } + + return 0; +} \ No newline at end of file diff --git a/launcher/launcher.rc b/launcher/launcher.rc new file mode 100644 index 0000000..21f11a4 --- /dev/null +++ b/launcher/launcher.rc @@ -0,0 +1,81 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Cursor +// + +IDC_NODROP CURSOR "nodrop.cur" + +//IDC_POINTER2 CURSOR "POINTER2.cur" + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON1 ICON "res\coollauncher.ico" + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/launcher/launcher.vpc b/launcher/launcher.vpc new file mode 100644 index 0000000..8c1d4af --- /dev/null +++ b/launcher/launcher.vpc @@ -0,0 +1,129 @@ +//----------------------------------------------------------------------------- +// LAUNCHER.VPC +// +// Project Script +//----------------------------------------------------------------------------- + +$Macro SRCDIR ".." +$Macro OUTBINDIR "$SRCDIR\..\game" + +$Include "$SRCDIR\vpc_scripts\source_exe_base.vpc" + +// Must be built explicitly as "default" in order to build a compliant submittable Disc. +// Renames will not work. +$Macro OUTBINNAME "default" +$Macro OUTBINNAME "hl2_osx" [$OSXALL] +$Macro OUTBINNAME "hl2_linux" [$LINUXALL] + +$Configuration +{ + $General + { + $AdditionalProjectDependencies "$BASE;togl" [$OSXALL] + } + $Compiler + { + //$PreprocessorDefinitions "$BASE;LAUNCHERONLY" + $PreprocessorDefinitions "$BASE;fopen=dont_use_fopen" + $ForceIncludes " " + } + + $Linker + { + $AdditionalDependencies "$BASE shlwapi.lib winmm.lib wsock32.lib odbc32.lib odbccp32.lib $SRCDIR\dx9sdk\lib\dinput8.lib $SRCDIR\dx9sdk\lib\ddraw.lib" [$WIN32] + $EnableLargeAddresses "Support Addresses Larger Than 2 Gigabytes (/LARGEADDRESSAWARE)" [$WIN32] + $FixedBaseAddress "Generate a relocation section (/FIXED:NO)" [$WIN32] + + $SystemLibraries "iconv" [$OSXALL] + $SystemFrameworks "Carbon;AppKit;OpenGL;IOKit" [$OSXALL] + // We run from the ./game dir, but want to look in the ./game/bin directory when loading libraries. + // To dump rpath/runpath of a library, use "chrpath --list blah.so" or "objdump -x blah.so" or "readelf -d bin/launcher.so" + $GCC_ExtraLinkerFlags "-Wl,--enable-new-dtags -Wl,-z,origin -Wl,-rpath,'$$ORIGIN' -L/usr/lib32 -L/usr/lib" [$LINUXALL] + } + + + $PreBuildEvent [$WIN32] + { + $CommandLine "if EXIST $OUTBINDIR\coolsource.exe for /f $QUOTEdelims=$QUOTE %%A in ('attrib $QUOTE$OUTBINDIR\coolsource.exe$QUOTE') do set valveTmpIsReadOnly=$QUOTE%%A$QUOTE" "\n" \ + "set valveTmpIsReadOnlyLetter=%valveTmpIsReadOnly:~6,1%" "\n" \ + "if $QUOTE%valveTmpIsReadOnlyLetter%$QUOTE==$QUOTER$QUOTE del /q $QUOTE$(TargetDir)$QUOTE$(TargetFileName)" "\n" \ + "$CRCCHECK" + } + + $PostBuildEvent [$X360] + { + // inherit and add + $CommandLine "$BASE" \ + "call $SRCDIR\vpc_scripts\valve_xbcp_wrapper.cmd $(TargetDir)$(TargetName).xex xE:\Valve\default.xex" "\n" + } + +} + +$Configuration "Debug" +{ + $Linker + { + $AdditionalDependencies "$BASE Xonlined.lib" [$X360] + } +} + +$Configuration "Release" +{ + $Linker + { + $AdditionalDependencies "$BASE Xonline.lib" [$X360] + } +} + +$Project "launcher" +{ + $Folder "Source Files" + { + $File "$SRCDIR\public\filesystem_init.cpp" + $File "launcher.cpp" + $File "reslistgenerator.cpp" + $File "launcher.rc" + } + + $Folder "Header Files" + { + $File "$SRCDIR\public\tier0\basetypes.h" + $File "$SRCDIR\public\tier0\commonmacros.h" + $File "$SRCDIR\public\tier0\dbg.h" + $File "$SRCDIR\common\engine_launcher_api.h" + $File "$SRCDIR\public\tier0\fasttimer.h" + $File "$SRCDIR\public\appframework\IAppSystem.h" + $File "$SRCDIR\public\tier0\icommandline.h" + $File "ifilesystem.h" + $File "$SRCDIR\public\vgui\IHTML.h" + $File "$SRCDIR\public\vgui\IImage.h" + $File "$SRCDIR\public\tier1\interface.h" + $File "$SRCDIR\public\vgui\ISurface.h" + $File "$SRCDIR\public\vgui\KeyCode.h" + $File "$SRCDIR\public\tier0\mem.h" + $File "$SRCDIR\public\tier0\memalloc.h" + $File "$SRCDIR\public\vgui\MouseCode.h" + $File "$SRCDIR\public\tier0\platform.h" + $File "$SRCDIR\public\tier0\protected_things.h" + $File "reslistgenerator.h" + $File "$SRCDIR\public\string_t.h" + $File "$SRCDIR\public\tier1\strtools.h" + $File "$SRCDIR\public\tier0\vcr_shared.h" + $File "$SRCDIR\public\tier0\vcrmode.h" + $File "$SRCDIR\public\mathlib\vector2d.h" + $File "$SRCDIR\public\vgui\VGUI.h" + $File "$SRCDIR\public\vstdlib\vstdlib.h" + } + + $folder "Link Libraries" + { + $Lib appframework + $Lib tier2 + $Lib tier3 + $Implib steam_api + $ImpLib togl [!$IS_LIB_PROJECT && $GL] + $ImpLib SDL2 [$SDL] + } + +} + diff --git a/launcher/nodrop.cur b/launcher/nodrop.cur new file mode 100644 index 0000000..a299255 Binary files /dev/null and b/launcher/nodrop.cur differ diff --git a/launcher/res/coollauncher.ico b/launcher/res/coollauncher.ico new file mode 100644 index 0000000..ef15e45 Binary files /dev/null and b/launcher/res/coollauncher.ico differ diff --git a/launcher/res/launcher.ico b/launcher/res/launcher.ico new file mode 100644 index 0000000..bda52dd Binary files /dev/null and b/launcher/res/launcher.ico differ diff --git a/launcher/reslistgenerator.cpp b/launcher/reslistgenerator.cpp new file mode 100644 index 0000000..51490db --- /dev/null +++ b/launcher/reslistgenerator.cpp @@ -0,0 +1,523 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// Defines the entry point for the application. +// +//===========================================================================// + +#include "reslistgenerator.h" +#include "filesystem.h" +#include "tier1/utlrbtree.h" +#include "tier1/fmtstr.h" +#include "characterset.h" +#include "tier1/utlstring.h" +#include "tier1/utlvector.h" +#include "tier1/utlbuffer.h" +#include "tier0/icommandline.h" +#include "tier1/KeyValues.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +bool SaveResList( const CUtlRBTree< CUtlString, int > &list, char const *pchFileName, char const *pchSearchPath ) +{ + FileHandle_t fh = g_pFullFileSystem->Open( pchFileName, "wt", pchSearchPath ); + if ( fh != FILESYSTEM_INVALID_HANDLE ) + { + for ( int i = list.FirstInorder(); i != list.InvalidIndex(); i = list.NextInorder( i ) ) + { + g_pFullFileSystem->Write( list[ i ].String(), Q_strlen( list[ i ].String() ), fh ); + g_pFullFileSystem->Write( "\n", 1, fh ); + } + + g_pFullFileSystem->Close( fh ); + return true; + } + return false; +} + +void LoadResList( CUtlRBTree< CUtlString, int > &list, char const *pchFileName, char const *pchSearchPath ) +{ + CUtlBuffer buffer( 0, 0, CUtlBuffer::TEXT_BUFFER ); + if ( !g_pFullFileSystem->ReadFile( pchFileName, pchSearchPath, buffer ) ) + { + // does not exist + return; + } + + characterset_t breakSet; + CharacterSetBuild( &breakSet, "" ); + + // parse reslist + char szToken[ MAX_PATH ]; + for ( ;; ) + { + int nTokenSize = buffer.ParseToken( &breakSet, szToken, sizeof( szToken ) ); + if ( nTokenSize <= 0 ) + { + break; + } + + Q_strlower( szToken ); + Q_FixSlashes( szToken ); + + // Ensure filename has "quotes" around it + CUtlString s; + if ( szToken[ 0 ] == '\"' ) + { + Assert( Q_strlen( szToken ) > 2 ); + Assert( szToken[ Q_strlen( szToken ) - 1 ] == '\"' ); + s = szToken; + } + else + { + s = CFmtStr( "\"%s\"", szToken ); + } + + int idx = list.Find( s ); + if ( idx == list.InvalidIndex() ) + { + list.Insert( s ); + } + } +} + +static bool ReslistLogLessFunc( CUtlString const &pLHS, CUtlString const &pRHS ) +{ + return CaselessStringLessThan( pLHS.Get(), pRHS.Get() ); +} + +void SortResList( char const *pchFileName, char const *pchSearchPath ) +{ + CUtlRBTree< CUtlString, int > sorted( 0, 0, ReslistLogLessFunc ); + LoadResList( sorted, pchFileName, pchSearchPath ); + + // Now write it back out + SaveResList( sorted, pchFileName, pchSearchPath ); +} + +void MergeResLists( CUtlVector< CUtlString > &fileNames, char const *pchOutputFile, char const *pchSearchPath ) +{ + CUtlRBTree< CUtlString, int > sorted( 0, 0, ReslistLogLessFunc ); + for ( int i = 0; i < fileNames.Count(); ++i ) + { + LoadResList( sorted, fileNames[ i ].String(), pchSearchPath ); + } + + // Now write it back out + SaveResList( sorted, pchOutputFile, pchSearchPath ); +} + +class CWorkItem +{ +public: + CWorkItem() + { + } + + CUtlString m_sSubDir; + CUtlString m_sAddCommands; +}; +class CResListGenerator: public IResListGenerator +{ +public: + enum + { + STATE_BUILDINGRESLISTS = 0, + STATE_GENERATINGCACHES, + }; + + CResListGenerator(); + + virtual void Init( char const *pchBaseDir, char const *pchGameDir ); + virtual bool IsActive(); + virtual void Shutdown(); + virtual void Collate(); + + virtual void SetupCommandLine(); + virtual bool ShouldContinue(); + +private: + + bool InitCommandFile( char const *pchGameDir, char const *pchCommandFile ); + void LoadMapList( char const *pchGameDir, CUtlVector< CUtlString > &vecMaps, char const *pchMapFile ); + void CollateFiles( char const *pchResListFilename ); + + bool m_bInitialized; + bool m_bActive; + CUtlString m_sBaseDir; + CUtlString m_sGameDir; + CUtlString m_sFullGamePath; + + CUtlString m_sFinalDir; + CUtlString m_sWorkingDir; + CUtlString m_sBaseCommandLine; + CUtlString m_sOriginalCommandLine; + CUtlString m_sInitialStartMap; + + int m_nCurrentWorkItem; + CUtlVector< CWorkItem > m_WorkItems; + + CUtlVector< CUtlString > m_MapList; + int m_nCurrentState; +}; + +static CResListGenerator g_ResListGenerator; +IResListGenerator *reslistgenerator = &g_ResListGenerator; + +CResListGenerator::CResListGenerator() : + m_bInitialized( false ), + m_bActive( false ), + m_nCurrentWorkItem( 0 ), + m_nCurrentState( STATE_BUILDINGRESLISTS ) +{ + MEM_ALLOC_CREDIT(); + + m_sFinalDir = "reslists"; + m_sWorkingDir = "reslists_work"; +} + +void CResListGenerator::CollateFiles( char const *pchResListFilename ) +{ + CUtlVector< CUtlString > vecReslists; + + for ( int i = 0; i < m_WorkItems.Count(); ++i ) + { + char fn[ MAX_PATH ]; + Q_snprintf( fn, sizeof( fn ), "%s\\%s\\%s\\%s", m_sFullGamePath.String(), m_sWorkingDir.String(), m_WorkItems[ i ].m_sSubDir.String(), pchResListFilename ); + vecReslists.AddToTail( fn ); + } + + MergeResLists( vecReslists, CFmtStr( "%s\\%s\\%s", m_sFullGamePath.String(), m_sFinalDir.String(), pchResListFilename ), "GAME" ); +} + +void CResListGenerator::Init( char const *pchBaseDir, char const *pchGameDir ) +{ + if ( IsX360() ) + { + // not used or supported + return; + } + + // Because we have to call this inside the first Apps "PreInit", we need only Init on the very first call + if ( m_bInitialized ) + { + return; + } + + m_bInitialized = true; + + m_sBaseDir = pchBaseDir; + m_sGameDir = pchGameDir; + + char path[MAX_PATH]; + Q_snprintf( path, sizeof(path), "%s/%s", m_sBaseDir.String(), m_sGameDir.String() ); + Q_FixSlashes( path ); + Q_strlower( path ); + m_sFullGamePath = path; + + const char *pchCommandFile = NULL; + if ( CommandLine()->CheckParm( "-makereslists", &pchCommandFile ) && pchCommandFile ) + { + // base path setup, now can get and parse command file + InitCommandFile( path, pchCommandFile ); + } +} + +void CResListGenerator::Shutdown() +{ + if ( !m_bActive ) + return; +} + +bool CResListGenerator::IsActive() +{ + return m_bInitialized && m_bActive; +} + +void CResListGenerator::Collate() +{ + char szDir[MAX_PATH]; + V_snprintf( szDir, sizeof( szDir ), "%s\\%s", m_sFullGamePath.String(), m_sFinalDir.String() ); + g_pFullFileSystem->CreateDirHierarchy( szDir, "GAME" ); + + // Now create the collated/merged data + CollateFiles( "all.lst" ); + CollateFiles( "engine.lst" ); + for ( int i = 0 ; i < m_MapList.Count(); ++i ) + { + CollateFiles( CFmtStr( "%s.lst", m_MapList[ i ].String() ) ); + } +} + +void CResListGenerator::SetupCommandLine() +{ + if ( !m_bActive ) + return; + + switch ( m_nCurrentState ) + { + case STATE_BUILDINGRESLISTS: + { + Assert( m_nCurrentWorkItem < m_WorkItems.Count() ); + + const CWorkItem &work = m_WorkItems[ m_nCurrentWorkItem ]; + + // Clean the working dir + char szWorkingDir[ 512 ]; + Q_snprintf( szWorkingDir, sizeof( szWorkingDir ), "%s\\%s", m_sWorkingDir.String(), work.m_sSubDir.String() ); + + char szFullWorkingDir[MAX_PATH]; + V_snprintf( szFullWorkingDir, sizeof( szFullWorkingDir ), "%s\\%s", m_sFullGamePath.String(), szWorkingDir ); + g_pFullFileSystem->CreateDirHierarchy( szFullWorkingDir, "GAME" ); + + // Preserve startmap + char const *pszStartMap = NULL; + CommandLine()->CheckParm( "-startmap", &pszStartMap ); + char szMap[ MAX_PATH ] = { 0 }; + if ( pszStartMap ) + { + Q_strncpy( szMap, pszStartMap, sizeof( szMap ) ); + } + + // Prepare stuff + // Reset command line based on current state + char szCmd[ 512 ]; + Q_snprintf( szCmd, sizeof( szCmd ), "%s %s %s -reslistdir %s", m_sOriginalCommandLine.String(), m_sBaseCommandLine.String(), work.m_sAddCommands.String(), szWorkingDir ); + + Warning( "Reslists: Setting command line:\n'%s'\n", szCmd ); + + CommandLine()->CreateCmdLine( szCmd ); + // Never rebuild caches by default, inly do it in STATE_GENERATINGCACHES + CommandLine()->AppendParm( "-norebuildaudio", NULL ); + if ( szMap[ 0 ] ) + { + CommandLine()->AppendParm( "-startmap", szMap ); + } + } + break; + case STATE_GENERATINGCACHES: + { + Collate(); + + // Prepare stuff + // Reset command line based on current state + char szCmd[ 512 ]; + Q_snprintf( szCmd, sizeof( szCmd ), "%s -reslistdir %s -rebuildaudio", m_sOriginalCommandLine.String(), m_sFinalDir.String()); + + Warning( "Caches: Setting command line:\n'%s'\n", szCmd ); + + CommandLine()->CreateCmdLine( szCmd ); + + CommandLine()->RemoveParm( "-norebuildaudio" ); + CommandLine()->RemoveParm( "-makereslists" ); + + ++m_nCurrentState; + } + break; + } +} + +bool CResListGenerator::ShouldContinue() +{ + if ( !m_bActive ) + return false; + + bool bContinueAdvancing = false; + do + { + switch ( m_nCurrentState ) + { + default: + break; + case STATE_BUILDINGRESLISTS: + { + CommandLine()->RemoveParm( "-startmap" ); + + // Advance to next time + ++m_nCurrentWorkItem; + + if ( m_nCurrentWorkItem >= m_WorkItems.Count()) + { + // Will stay in the loop + ++m_nCurrentState; + bContinueAdvancing = true; + } + else + { + return true; + } + } + break; + case STATE_GENERATINGCACHES: + { + return true; + } + break; + } + } while ( bContinueAdvancing ); + + return false; +} + +void CResListGenerator::LoadMapList( char const *pchGameDir, CUtlVector< CUtlString > &vecMaps, char const *pchMapFile ) +{ + char fullpath[ 512 ]; + Q_snprintf( fullpath, sizeof( fullpath ), "%s/%s", pchGameDir, pchMapFile ); + + // Load them in + CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); + + if ( g_pFullFileSystem->ReadFile( fullpath, "GAME", buf ) ) + { + char szMap[ MAX_PATH ]; + while ( true ) + { + buf.GetLine( szMap, sizeof( szMap ) ); + if ( !szMap[ 0 ] ) + break; + + // Strip trailing CR/LF chars + int len = Q_strlen( szMap ); + while ( len >= 1 && ( szMap[ len - 1 ] == '\n' || szMap[ len - 1 ] == '\r' ) ) + { + szMap[ len - 1 ] = 0; + len = Q_strlen( szMap ); + } + + CUtlString newMap; + newMap = szMap; + vecMaps.AddToTail( newMap ); + } + } + else + { + Error( "Unable to maplist file %s\n", fullpath ); + } +} + +bool CResListGenerator::InitCommandFile( char const *pchGameDir, char const *pchCommandFile ) +{ + if ( *pchCommandFile == '+' || + *pchCommandFile == '-' ) + { + Msg( "falling back to legacy reslists system\n" ); + return false; + } + + char fullpath[ 512 ]; + Q_snprintf( fullpath, sizeof( fullpath ), "%s/%s", pchGameDir, pchCommandFile ); + + CUtlBuffer buf; + if ( !g_pFullFileSystem->ReadFile( fullpath, "GAME", buf ) ) + { + Error( "Unable to load '%s'\n", fullpath ); + return false; + } + + KeyValues *kv = new KeyValues( "reslists" ); + if ( !kv->LoadFromBuffer( "reslists", (const char *)buf.Base() ) ) + { + Error( "Unable to parse keyvalues from '%s'\n", fullpath ); + kv->deleteThis(); + return false; + } + + CUtlString sMapListFile = kv->GetString( "maplist", "maplist.txt" ); + LoadMapList( pchGameDir, m_MapList, sMapListFile ); + if ( m_MapList.Count() <= 0 ) + { + Error( "Maplist file '%s' empty or missing!!!\n", sMapListFile.String() ); + kv->deleteThis(); + return false; + } + + char const *pszSolo = NULL; + if ( CommandLine()->CheckParm( "+map", &pszSolo ) && pszSolo ) + { + m_MapList.Purge(); + + CUtlString newMap; + newMap = pszSolo; + m_MapList.AddToTail( newMap ); + } + + m_nCurrentWorkItem = CommandLine()->ParmValue( "-startstage", 0 ); + + char const *pszStartMap = NULL; + CommandLine()->CheckParm( "-startmap", &pszStartMap ); + if ( pszStartMap ) + { + m_sInitialStartMap = pszStartMap; + } + + CommandLine()->RemoveParm( "-startstage" ); + CommandLine()->RemoveParm( "-makereslists" ); + CommandLine()->RemoveParm( "-reslistdir" ); + CommandLine()->RemoveParm( "-norebuildaudio" ); + CommandLine()->RemoveParm( "-startmap" ); + + m_sOriginalCommandLine = CommandLine()->GetCmdLine(); + + // Add it back in for first map + if ( pszStartMap ) + { + CommandLine()->AppendParm( "-startmap", m_sInitialStartMap.String() ); + } + + m_sBaseCommandLine = kv->GetString( "basecommandline", "" ); + m_sFinalDir = kv->GetString( "finaldir", m_sFinalDir.String() ); + m_sWorkingDir = kv->GetString( "workdir", m_sWorkingDir.String() ); + + int i = 0; + do + { + char sz[ 32 ]; + Q_snprintf( sz, sizeof( sz ), "%i", i ); + KeyValues *subKey = kv->FindKey( sz, false ); + if ( !subKey ) + break; + + CWorkItem work; + + work.m_sSubDir = subKey->GetString( "subdir", "" ); + work.m_sAddCommands = subKey->GetString( "addcommands", "" ); + + if ( work.m_sSubDir.Length() > 0 ) + { + m_WorkItems.AddToTail( work ); + } + else + { + Error( "%s: failed to specify 'subdir' for item %s\n", fullpath, sz ); + } + + ++i; + } while ( true ); + + m_bActive = m_WorkItems.Count() > 0; + + m_nCurrentWorkItem = clamp( m_nCurrentWorkItem, 0, m_WorkItems.Count() - 1 ); + + bool bCollate = CommandLine()->CheckParm( "-collate" ) ? true : false; + if ( bCollate ) + { + Collate(); + m_bActive = false; + exit( -1 ); + } + + kv->deleteThis(); + + /* + if ( m_bActive ) + { + // Wipe console log + g_pFullFileSystem->RemoveFile( "console.log", "GAME" ); + } + */ + return m_bActive; +} + + diff --git a/launcher/reslistgenerator.h b/launcher/reslistgenerator.h new file mode 100644 index 0000000..f386069 --- /dev/null +++ b/launcher/reslistgenerator.h @@ -0,0 +1,32 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// Defines the entry point for the application. +// +//===========================================================================// + +#ifndef RESLISTGENERATOR_H +#define RESLISTGENERATOR_H + +#ifdef _WIN32 +#pragma once +#endif + +class IResListGenerator +{ +public: + + virtual void Init( char const *pchBaseDir, char const *pchGameDir ) = 0; + virtual void Shutdown() = 0; + virtual bool IsActive() = 0; + + virtual void SetupCommandLine() = 0; + + virtual bool ShouldContinue() = 0; +}; + +extern IResListGenerator *reslistgenerator; + +#endif // RESLISTGENERATOR_H + diff --git a/launcher/resource.h b/launcher/resource.h new file mode 100644 index 0000000..39cddbc --- /dev/null +++ b/launcher/resource.h @@ -0,0 +1,17 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by launcher.rc +// +#define IDC_NODROP 106 +#define IDI_ICON1 111 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 112 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/launcher/xbox/xbox.def b/launcher/xbox/xbox.def new file mode 100644 index 0000000..72fc25a --- /dev/null +++ b/launcher/xbox/xbox.def @@ -0,0 +1,3 @@ +LIBRARY launcher_360.dll +EXPORTS + LauncherMain @1 \ No newline at end of file diff --git a/lib/public/mathlib.lib b/lib/public/mathlib.lib index 5225f79..1643dc8 100644 Binary files a/lib/public/mathlib.lib and b/lib/public/mathlib.lib differ diff --git a/lib/public/tier1.lib b/lib/public/tier1.lib index 196529c..6108ef4 100644 Binary files a/lib/public/tier1.lib and b/lib/public/tier1.lib differ diff --git a/lib/public/vgui_controls.lib b/lib/public/vgui_controls.lib index d448d7b..6cc72e7 100644 Binary files a/lib/public/vgui_controls.lib and b/lib/public/vgui_controls.lib differ diff --git a/lib/public/vtf.lib b/lib/public/vtf.lib index fee7da1..4ffcb72 100644 Binary files a/lib/public/vtf.lib and b/lib/public/vtf.lib differ diff --git a/vpc_scripts/projects.vgc b/vpc_scripts/projects.vgc index 8d7e521..70040af 100644 --- a/vpc_scripts/projects.vgc +++ b/vpc_scripts/projects.vgc @@ -1,186 +1,191 @@ -//----------------------------------------------------------------------------- -// PROJECTS.VGC -// -// Project Configurations for all Source(TM) Projects -//----------------------------------------------------------------------------- - -///////////////////////// -// Project definitions // -///////////////////////// - -$Project "captioncompiler" -{ - "utils\captioncompiler\captioncompiler.vpc" [$WIN32] -} - - -$Project "client" -{ - "game\client\client_hl2mp.vpc" [($WIN32||$POSIX) && $HL2MP] - "game\client\client_episodic.vpc" [($WIN32||$POSIX) && $EPISODIC] - "game\client\client_hl2.vpc" [($WIN32||$POSIX) && $HL2] - "game\client\client_sdk.vpc" [($WIN32||$POSIX) && $SDK] -} - -$Project "fgdlib" -{ - "fgdlib\fgdlib.vpc" [$WIN32] -} - -$Project "game_shader_dx9" -{ - "materialsystem\stdshaders\game_shader_dx9_hl2mp.vpc" [$HL2MP] -} - -$Project "glview" -{ - "utils\glview\glview.vpc" [$WIN32] -} - -$Project "height2normal" -{ - "utils\height2normal\height2normal.vpc" [$WIN32] -} - -$Project "server" -{ - "game\server\server_hl2mp.vpc" [($WIN32||$POSIX) && $HL2MP] - "game\server\server_episodic.vpc" [($WIN32||$POSIX) && $EPISODIC] - "game\server\server_hl2.vpc" [($WIN32||$POSIX) && $HL2] - "game\server\server_sdk.vpc" [($WIN32||$POSIX) && $SDK] -} - -$Project "mathlib" -{ - "mathlib\mathlib.vpc" [$WINDOWS||$X360||$POSIX] -} - -$Project "motionmapper" -{ - "utils\motionmapper\motionmapper.vpc" [$WIN32] -} - -$Project "phonemeextractor" -{ - "utils\phonemeextractor\phonemeextractor.vpc" [$WIN32] -} - -$Project "raytrace" -{ - "raytrace\raytrace.vpc" [$WIN32||$X360||$POSIX] -} - -$Project "qc_eyes" -{ - "utils\qc_eyes\qc_eyes.vpc" [$WIN32] -} - -$Project "serverplugin_empty" -{ - "utils\serverplugin_sample\serverplugin_empty.vpc" [$WIN32||$POSIX] -} - -$Project "shaderapidx9" -{ - "materialsystem\shaderapidx9\shaderapidx9.vpc" -} - -$Project "tgadiff" -{ - "utils\tgadiff\tgadiff.vpc" [$WIN32] -} - -$Project "tier1" -{ - "tier1\tier1.vpc" [$WINDOWS || $X360||$POSIX] -} - -$Project "vbsp" -{ - "utils\vbsp\vbsp.vpc" [$WIN32] -} - -$Project "vgui_controls" -{ - "vgui2\vgui_controls\vgui_controls.vpc" [$WIN32||$X360||$POSIX] -} - -$Project "vice" -{ - "utils\vice\vice.vpc" [$WIN32] -} - -$Project "vrad_dll" -{ - "utils\vrad\vrad_dll.vpc" [$WIN32] -} - -$Project "vrad_launcher" -{ - "utils\vrad_launcher\vrad_launcher.vpc" [$WIN32] -} - -$Project "vtf2tga" -{ - "utils\vtf2tga\vtf2tga.vpc" [$WIN32] -} - -$Project "vtfdiff" -{ - "utils\vtfdiff\vtfdiff.vpc" [$WIN32] -} - -$Project "vvis_dll" -{ - "utils\vvis\vvis_dll.vpc" [$WIN32] -} - -$Project "vvis_launcher" -{ - "utils\vvis_launcher\vvis_launcher.vpc" [$WIN32] -} - -$Project "vpklib" -{ - "vpklib/vpklib.vpc" [$WIN32] -} - -$Project "vtf" -{ - "vtf/vtf.vpc" [$WIN32] -} - -$Project "engine" -{ - "engine/engine.vpc" [$WIN32] -} - -$Project "materialsystem" -{ - "materialsystem/materialsystem.vpc" [$WIN32] -} - -$Project "studiorender" -{ - "studiorender\studiorender.vpc" [$WIN32] -} - -$Project "filesystem_stdio" -{ - "filesystem/filesystem_stdio.vpc" [$WIN32] -} - -$Project "filesystem_steam" -{ - "filesystem/filesystem_steam.vpc" [$WIN32] -} - -$Project "bsppack" -{ - "utils\bsppack\bsppack.vpc" [$WIN32] -} - -$Project "bspzip" -{ - "utils\bspzip\bspzip.vpc" [$WIN32] +//----------------------------------------------------------------------------- +// PROJECTS.VGC +// +// Project Configurations for all Source(TM) Projects +//----------------------------------------------------------------------------- + +///////////////////////// +// Project definitions // +///////////////////////// + +$Project "captioncompiler" +{ + "utils\captioncompiler\captioncompiler.vpc" [$WIN32] +} + + +$Project "client" +{ + "game\client\client_hl2mp.vpc" [($WIN32||$POSIX) && $HL2MP] + "game\client\client_episodic.vpc" [($WIN32||$POSIX) && $EPISODIC] + "game\client\client_hl2.vpc" [($WIN32||$POSIX) && $HL2] + "game\client\client_sdk.vpc" [($WIN32||$POSIX) && $SDK] +} + +$Project "fgdlib" +{ + "fgdlib\fgdlib.vpc" [$WIN32] +} + +$Project "game_shader_dx9" +{ + "materialsystem\stdshaders\game_shader_dx9_hl2mp.vpc" [$HL2MP] +} + +$Project "glview" +{ + "utils\glview\glview.vpc" [$WIN32] +} + +$Project "coolsource" //this is the launcher +{ + "launcher\launcher.vpc" +} + +$Project "height2normal" +{ + "utils\height2normal\height2normal.vpc" [$WIN32] +} + +$Project "server" +{ + "game\server\server_hl2mp.vpc" [($WIN32||$POSIX) && $HL2MP] + "game\server\server_episodic.vpc" [($WIN32||$POSIX) && $EPISODIC] + "game\server\server_hl2.vpc" [($WIN32||$POSIX) && $HL2] + "game\server\server_sdk.vpc" [($WIN32||$POSIX) && $SDK] +} + +$Project "mathlib" +{ + "mathlib\mathlib.vpc" [$WINDOWS||$X360||$POSIX] +} + +$Project "motionmapper" +{ + "utils\motionmapper\motionmapper.vpc" [$WIN32] +} + +$Project "phonemeextractor" +{ + "utils\phonemeextractor\phonemeextractor.vpc" [$WIN32] +} + +$Project "raytrace" +{ + "raytrace\raytrace.vpc" [$WIN32||$X360||$POSIX] +} + +$Project "qc_eyes" +{ + "utils\qc_eyes\qc_eyes.vpc" [$WIN32] +} + +$Project "serverplugin_empty" +{ + "utils\serverplugin_sample\serverplugin_empty.vpc" [$WIN32||$POSIX] +} + +$Project "shaderapidx9" +{ + "materialsystem\shaderapidx9\shaderapidx9.vpc" +} + +$Project "tgadiff" +{ + "utils\tgadiff\tgadiff.vpc" [$WIN32] +} + +$Project "tier1" +{ + "tier1\tier1.vpc" [$WINDOWS || $X360||$POSIX] +} + +$Project "vbsp" +{ + "utils\vbsp\vbsp.vpc" [$WIN32] +} + +$Project "vgui_controls" +{ + "vgui2\vgui_controls\vgui_controls.vpc" [$WIN32||$X360||$POSIX] +} + +$Project "vice" +{ + "utils\vice\vice.vpc" [$WIN32] +} + +$Project "vrad_dll" +{ + "utils\vrad\vrad_dll.vpc" [$WIN32] +} + +$Project "vrad_launcher" +{ + "utils\vrad_launcher\vrad_launcher.vpc" [$WIN32] +} + +$Project "vtf2tga" +{ + "utils\vtf2tga\vtf2tga.vpc" [$WIN32] +} + +$Project "vtfdiff" +{ + "utils\vtfdiff\vtfdiff.vpc" [$WIN32] +} + +$Project "vvis_dll" +{ + "utils\vvis\vvis_dll.vpc" [$WIN32] +} + +$Project "vvis_launcher" +{ + "utils\vvis_launcher\vvis_launcher.vpc" [$WIN32] +} + +$Project "vpklib" +{ + "vpklib/vpklib.vpc" [$WIN32] +} + +$Project "vtf" +{ + "vtf/vtf.vpc" [$WIN32] +} + +$Project "engine" +{ + "engine/engine.vpc" [$WIN32] +} + +$Project "materialsystem" +{ + "materialsystem/materialsystem.vpc" [$WIN32] +} + +$Project "studiorender" +{ + "studiorender\studiorender.vpc" [$WIN32] +} + +$Project "filesystem_stdio" +{ + "filesystem/filesystem_stdio.vpc" [$WIN32] +} + +$Project "filesystem_steam" +{ + "filesystem/filesystem_steam.vpc" [$WIN32] +} + +$Project "bsppack" +{ + "utils\bsppack\bsppack.vpc" [$WIN32] +} + +$Project "bspzip" +{ + "utils\bspzip\bspzip.vpc" [$WIN32] } \ No newline at end of file diff --git a/vpc_scripts/valve_p4_edit.cmd b/vpc_scripts/valve_p4_edit.cmd new file mode 100644 index 0000000..64454fc --- /dev/null +++ b/vpc_scripts/valve_p4_edit.cmd @@ -0,0 +1,84 @@ +@echo off + +setlocal + +set valveTmpFileFromVS2005=%1% +set valveTmpFileFromVS2005=%valveTmpFileFromVS2005:\\=\% + +set valveChangelistName="Visual Studio Auto Checkout" + +:: // Make sure we have 2 args +if .%2.==.. ( + echo *** [valve_p4_edit] Error calling command! No file specified for checkout! + echo *** Usage: valve_p4_edit.cmd file srcdir ["changelist name"] + echo *** The changelist name is optional. If present, must be quoted. By default it's %valveChangelistName%. + endlocal + exit /b 1 +) + +if [%3] NEQ [] ( + set valveChangelistName=%3 +) + +:: // Fallback to old functionality and just change file attribs +if NOT "%VALVE_NO_AUTO_P4%"=="" ( + echo [valve_p4_edit] VALVE_NO_AUTO_P4 defined. Changing file attribs only! + if EXIST %valveTmpFileFromVS2005% ( + attrib -r %valveTmpFileFromVS2005% + ) + endlocal + exit /b 0 +) + +rem // :: // First check if file exists +rem // if NOT EXIST %valveTmpFileFromVS2005% ( +rem // :: // File does not exist +rem // rem // echo [valve_p4_edit] %valveTmpFileFromVS2005% does not exist! Skipping p4 edit command. +rem // endlocal +rem // exit /b 0 +rem // ) +rem // +rem // :: // Check if file is read-only (NOTE: If the file is writable, we don't call p4!) +rem // dir /b /ar %valveTmpFileFromVS2005% >nul 2>&1 +rem // if NOT %ERRORLEVEL%==0 ( +rem // rem // echo [valve_p4_edit] %valveTmpFileFromVS2005% is already writable. Not calling p4 edit. +rem // endlocal +rem // exit /b 0 +rem // ) + +:: // Put 360 bins into their own changelist +for /f %%A in ('echo %valveTmpFileFromVS2005% ^| find /i "360"') do set valveTmpIs360=%%A +if NOT "%valveTmpIs360%"=="" ( + set valveChangelistName="360 Visual Studio Auto Checkout" +) + +for /f %%A in ('echo %valveTmpFileFromVS2005% ^| find /i "launcher_main"') do set valveTmpIs360=%%A +if NOT "%valveTmpIs360%"=="" ( + set valveChangelistName="360 Visual Studio Auto Checkout" +) + +set valveP4EditCall=%2\devtools\bin\valve_p4_edit_to_changelist.cmd %valveTmpFileFromVS2005% %valveChangelistName% + +if "%VALVE_WAIT_ON_P4%"=="" ( + :: // The file exists and is read-only, so change the file attrib and spawn the Perforce checkout asynchronously + if EXIST %valveTmpFileFromVS2005% attrib -r %valveTmpFileFromVS2005% + start /b cmd /c %valveP4EditCall% EXIT + rem // (NOTE: The EXIT arg is needed because we're using the start command to launch the cmd!) +) ELSE ( + :: // Do not use attrib -r if we're doing synchronous p4 edit. If this fails, we want to throw an error below + call %valveP4EditCall% +) + +:: // Make sure file is writable if it exists +if NOT EXIST %valveTmpFileFromVS2005% goto End +dir /b /a-r %valveTmpFileFromVS2005% >nul 2>&1 +if NOT %ERRORLEVEL%==0 ( + :: // Return with an error to stop the build! + echo *** [valve_p4_edit] Error! %valveTmpFileFromVS2005% is not writable! + endlocal + exit /b 1 +) + +:End +endlocal +exit /b 0 \ No newline at end of file diff --git a/vpc_scripts/valve_p4_edit.pl b/vpc_scripts/valve_p4_edit.pl new file mode 100644 index 0000000..e6aa99f --- /dev/null +++ b/vpc_scripts/valve_p4_edit.pl @@ -0,0 +1,52 @@ +#!/usr/bin/perl -w + +use Data::Dumper; +use FindBin; +use Cwd qw(getcwd abs_path); +use File::Basename; +use lib "$FindBin::Bin/../devtools/lib"; +use P4Run; +use strict; + +die "Usage: $0 \n" unless @ARGV; +my $path = shift @ARGV; +my $dir = abs_path(dirname($path)); +my $file = "$dir/".basename($path); + +if ($ENV{VALVE_NO_AUTO_P4}) +{ + print "VALVE_NO_AUTO_P4 Set. Making $file writable\n"; + if ($^O eq 'MSWin32') + { + system('attrib', '-r', $file); + } + else + { + open(my $fh, "<", $file); + my $perm = (stat($fh))[2] | 0220; + chmod $perm, $fh; + } +} +else +{ + my $desc = $^O eq 'MSWin32' ? 'Visual Studio Auto Checkout' : 'GCC Auto Checkout'; + $desc = '360 Visual Studio Auto Checkout' if $file =~ /_360|launcher_main|default.xex/; + my $change = P4Run::FindChange($desc) || P4Run::NewChange($desc); + die "Failed to create Change List: $desc\n" unless $change; + my ($stat) = P4Run('fstat', $file); + if ($stat) + { + print "Opening $file for edit in CL#$change ($desc)\n"; + P4Run('edit', '-c', $change, $file); + } + else + { + print "Adding new file $file to CL#$change ($desc)\n"; + open(my $fh, ">", $file); close($fh); + P4Run('add', '-c', $change, '-t', 'xbinary', $file); + unlink($file); + } +} + +warn "$file is not writable\n" if (-e $file && ! -w $file); +exit 0; diff --git a/vpc_scripts/valve_xbcp_wrapper.cmd b/vpc_scripts/valve_xbcp_wrapper.cmd new file mode 100644 index 0000000..eab6e87 --- /dev/null +++ b/vpc_scripts/valve_xbcp_wrapper.cmd @@ -0,0 +1,28 @@ +@echo off + +setlocal + + +:: // If they've disabled xbcp, then don't use it. +if NOT "%VALVE_NO_XBCP%"=="" ( + echo [valve_xbcp_wrapper] VALVE_NO_XBCP defined. Avoiding the copy. + endlocal + exit /b 0 +) + + +set localFilename=%1 +set remoteFilename=%2 + +"%XEDK%\bin\win32\xbcp" /y /t "%localFilename%" "%remoteFilename%" + +if %ERRORLEVEL%==1 ( + echo XBCP failed. If you don't have an X360 but want to compile its sources, define VALVE_NO_XBCP. + del /q %1% + exit 1 +) + + +:End +endlocal +exit /b 0