From b0b66cbf47ad28ca55ef29dc555af5e31b1b13da Mon Sep 17 00:00:00 2001 From: Scott Ehlert Date: Thu, 20 Mar 2008 23:08:35 +0000 Subject: [PATCH] Fixed amb1523 - Crash on The Ship due to unavailable IFileSystem functions which are used in KeyValues::LoadFromFile() --HG-- branch : sourcemm-1.4.4 extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/branches/sourcemm-1.4.4%40683 --- sourcemm/sourcemm.cpp | 48 +++++++++++++++++++++++++++++++++++++++++-- sourcemm/sourcemm.h | 3 ++- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/sourcemm/sourcemm.cpp b/sourcemm/sourcemm.cpp index d1f3210..0e3abb4 100644 --- a/sourcemm/sourcemm.cpp +++ b/sourcemm/sourcemm.cpp @@ -46,6 +46,7 @@ void LevelShutdown_handler(); bool LevelInit_handler(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background); bool GameInit_handler(); void LookForVDFs(const char *dir); +bool KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL); GameDllInfo g_GameDll = {false, NULL, NULL, NULL, NULL}; EngineInfo g_Engine; @@ -167,6 +168,9 @@ bool StartupMetamod(CreateInterfaceFn engineFactory, bool bWaitForGameInit) g_Engine.loaded = true; + /* The Ship is the only game known at this time that uses the pre-Episode One engine */ + g_Engine.original = strcmp(CommandLine()->ParmValue("-game", "hl2"), "ship") == 0; + ConCommandBaseMgr::OneTimeInit(static_cast(&g_SMConVarAccessor)); g_GameDllPatch = SH_GET_CALLCLASS(g_GameDll.pGameDLL); @@ -625,14 +629,24 @@ void DLLShutdown_handler() void LoadFromVDF(const char *file) { PluginId id; - bool already; + bool already, kvfileLoaded; KeyValues *pValues; const char *plugin_file, *alias; char full_path[256], error[256]; pValues = new KeyValues("Metamod Plugin"); - if (!pValues->LoadFromFile(baseFs, file)) + if (g_Engine.original) + { + /* The Ship must use a special version of this function */ + kvfileLoaded = KVLoadFromFile(pValues, baseFs, file); + } + else + { + kvfileLoaded = pValues->LoadFromFile(baseFs, file); + } + + if (!kvfileLoaded) { pValues->deleteThis(); return; @@ -751,6 +765,36 @@ void LookForVDFs(const char *dir) #endif } +bool KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, const char *resourceName, const char *pathID) +{ + Assert(filesystem); +#ifdef _MSC_VER + Assert(_heapchk() == _HEAPOK); +#endif + + FileHandle_t f = filesystem->Open(resourceName, "rb", pathID); + if (!f) + return false; + + // load file into a null-terminated buffer + int fileSize = filesystem->Size(f); + char *buffer = (char *)MemAllocScratch(fileSize + 1); + + Assert(buffer); + + filesystem->Read(buffer, fileSize, f); // read into local buffer + + buffer[fileSize] = 0; // null terminate file as EOF + + filesystem->Close( f ); // close file after reading + + bool retOK = kv->LoadFromBuffer( resourceName, buffer, filesystem ); + + MemFreeScratch(); + + return retOK; +} + int LoadPluginsFromFile(const char *_file) { FILE *fp; diff --git a/sourcemm/sourcemm.h b/sourcemm/sourcemm.h index 05fd0b6..61a58c7 100644 --- a/sourcemm/sourcemm.h +++ b/sourcemm/sourcemm.h @@ -74,11 +74,12 @@ struct GameDllInfo /** @brief Stores information about the HL2 Engine pointers */ struct EngineInfo { - EngineInfo() : loaded(false), + EngineInfo() : loaded(false), original(false), engineFactory(NULL), physicsFactory(NULL), fileSystemFactory(NULL), pGlobals(NULL), icvar(NULL), engine(NULL) { }; bool loaded; + bool original; CreateInterfaceFn engineFactory; CreateInterfaceFn physicsFactory; CreateInterfaceFn fileSystemFactory;