1
0
mirror of https://github.com/alliedmodders/metamod-source.git synced 2024-11-29 11:24:19 +01:00

Merge pull request #31 from alliedmodders/S2

Re-add support for Dota 2 (on Source 2, and x64)
This commit is contained in:
Nicholas Hastings 2017-04-22 22:43:55 -04:00 committed by GitHub
commit a876b9c1fb
25 changed files with 1676 additions and 207 deletions

View File

@ -8,13 +8,30 @@ class SDK(object):
self.ext = ext
self.code = aDef
self.define = name
self.platform = platform
self.name = dir
self.path = None # Actual path
self.platformSpec = platform
# By default, nothing supports x64.
if type(platform) is list:
self.platformSpec = {p: ['x86'] for p in platform}
else:
self.platformSpec = platform
def shouldBuild(self, target):
if target.platform not in self.platformSpec:
return False
if target.arch not in self.platformSpec[target.platform]:
return False
return True
WinOnly = ['windows']
WinLinux = ['windows', 'linux']
WinLinuxMac = ['windows', 'linux', 'mac']
Source2 = {
'windows': ['x86', 'x86_64'],
'linux': ['x86_64'],
}
PossibleSDKs = {
'episode1': SDK('HL2SDK', '2.ep1', '1', 'EPISODEONE', WinLinux, 'episode1'),
@ -32,7 +49,7 @@ PossibleSDKs = {
'bgt': SDK('HL2SDK-BGT', '2.bgt', '4', 'BLOODYGOODTIME', WinOnly, 'bgt'),
'eye': SDK('HL2SDK-EYE', '2.eye', '5', 'EYE', WinOnly, 'eye'),
'csgo': SDK('HL2SDKCSGO', '2.csgo', '20', 'CSGO', WinLinuxMac, 'csgo'),
'dota': SDK('HL2SDKDOTA', '2.dota', '21', 'DOTA', [], 'dota'),
'dota': SDK('HL2SDKDOTA', '2.dota', '21', 'DOTA', Source2, 'dota'),
'portal2': SDK('HL2SDKPORTAL2', '2.portal2', '17', 'PORTAL2', [], 'portal2'),
'blade': SDK('HL2SDKBLADE', '2.blade', '18', 'BLADE', WinLinux, 'blade'),
'insurgency': SDK('HL2SDKINSURGENCY', '2.insurgency', '19', 'INSURGENCY', WinLinuxMac, 'insurgency'),
@ -92,7 +109,7 @@ class MMSConfig(object):
for sdk_name in PossibleSDKs:
sdk = PossibleSDKs[sdk_name]
if builder.target_platform in sdk.platform:
if sdk.shouldBuild(builder.target):
if builder.options.hl2sdk_root:
sdk_path = os.path.join(builder.options.hl2sdk_root, sdk.folder)
else:
@ -106,16 +123,19 @@ class MMSConfig(object):
self.sdks[sdk_name] = sdk
if len(self.sdks) < 1 and len(sdk_list):
raise Exception('At least one SDK must be available.')
raise Exception('No SDKs were found that build on {0}-{1}, nothing to do.'.format(
builder.target.platform, builder.target.arch))
def configure(self):
builder.AddConfigureFile('pushbuild.txt')
cfg = builder.DetectCompilers()
cxx = cfg.cxx
if builder.target.arch not in ['x86', 'x86_64']:
raise Exception('Unknown target architecture: {0}'.format(builder.target.arch))
cxx = builder.DetectCxx()
if cxx.behavior == 'gcc':
cfg.defines += [
cxx.defines += [
'stricmp=strcasecmp',
'_stricmp=strcasecmp',
'_snprintf=snprintf',
@ -123,7 +143,7 @@ class MMSConfig(object):
'HAVE_STDINT_H',
'GNUC',
]
cfg.cflags += [
cxx.cflags += [
'-pipe',
'-fno-strict-aliasing',
'-Wall',
@ -132,52 +152,63 @@ class MMSConfig(object):
'-Wno-unused',
'-Wno-switch',
'-msse',
'-m32',
]
cfg.cxxflags += [ '-std=c++11' ]
if (cxx.name == 'gcc' and cxx.majorVersion >= 4) or cxx.name == 'clang':
cfg.cflags += ['-fvisibility=hidden']
cfg.cxxflags += ['-fvisibility-inlines-hidden']
cfg.linkflags += ['-m32']
cfg.cxxflags += [
if builder.target.arch == 'x86':
cxx.cflags += ['-m32']
cxx.linkflags += ['-m32']
elif builder.target.arch == 'x86_64':
cxx.cflags += ['-m64', '-fPIC']
cxx.linkflags += ['-m64']
cxx.cxxflags += [ '-std=c++11' ]
if (cxx.version >= 'gcc-4.0') or cxx.family == 'clang':
cxx.cflags += ['-fvisibility=hidden']
cxx.cxxflags += ['-fvisibility-inlines-hidden']
cxx.cxxflags += [
'-fno-exceptions',
'-fno-rtti',
'-fno-threadsafe-statics',
'-Wno-non-virtual-dtor',
'-Wno-overloaded-virtual',
]
if (cxx.name == 'gcc' and cfg.version >= 'gcc-4.7') or \
(cxx.name == 'clang' and cxx.majorVersion >= 3):
cfg.cxxflags += ['-Wno-delete-non-virtual-dtor']
if cxx.name == 'gcc':
cfg.cflags += ['-mfpmath=sse']
if cxx.name == 'clang':
if cfg.version >= 'clang-3.6':
cfg.cxxflags += ['-Wno-inconsistent-missing-override']
cfg.cxxflags += ['-Wno-implicit-exception-spec-mismatch']
if cfg.version >= 'apple-clang-5.1' or cfg.version >= 'clang-3.4':
cfg.cxxflags += ['-Wno-deprecated-register']
if (cxx.version >= 'gcc-4.7' or cxx.version >= 'clang-3.0'):
cxx.cxxflags += ['-Wno-delete-non-virtual-dtor']
if cxx.family == 'gcc':
cxx.cflags += ['-mfpmath=sse']
if cxx.family == 'clang':
cxx.cxxflags += [
'-Wno-implicit-exception-spec-mismatch',
'-Wno-inconsistent-missing-override',
]
if cxx.version >= 'apple-clang-5.1' or cxx.version >= 'clang-3.4':
cxx.cxxflags += ['-Wno-deprecated-register']
else:
cfg.cxxflags += ['-Wno-deprecated']
cxx.cxxflags += ['-Wno-deprecated']
elif cxx.name == 'msvc':
elif cxx.like('msvc'):
if builder.options.debug == '1':
cfg.cflags += ['/MTd']
cfg.linkflags += ['/NODEFAULTLIB:libcmt']
cxx.cflags += ['/MTd']
cxx.linkflags += ['/NODEFAULTLIB:libcmt']
else:
cfg.cflags += ['/MT']
cfg.defines += [
cxx.cflags += ['/MT']
cxx.defines += [
'_CRT_SECURE_NO_DEPRECATE',
'_CRT_SECURE_NO_WARNINGS',
'_CRT_NONSTDC_NO_DEPRECATE',
]
cfg.cflags += [
cxx.cflags += [
'/W3',
'/Zi',
]
cfg.cxxflags += ['/TP']
cfg.linkflags += [
'/MACHINE:X86',
cxx.cxxflags += ['/TP']
if builder.target.arch == 'x86':
cxx.linkflags += ['/MACHINE:X86']
elif builder.target.arch == 'x86_64':
cxx.linkflags += ['/MACHINE:X64']
cxx.linkflags += [
'/SUBSYSTEM:WINDOWS',
'kernel32.lib',
'user32.lib',
@ -195,58 +226,58 @@ class MMSConfig(object):
# Optimization
if builder.options.opt == '1':
cfg.defines += ['NDEBUG']
cxx.defines += ['NDEBUG']
if cxx.behavior == 'gcc':
cfg.cflags += ['-O3']
cxx.cflags += ['-O3']
elif cxx.behavior == 'msvc':
cfg.cflags += ['/Ox', '/Zo']
cfg.linkflags += ['/OPT:ICF', '/OPT:REF']
cxx.cflags += ['/Ox', '/Zo']
cxx.linkflags += ['/OPT:ICF', '/OPT:REF']
# Debugging
if builder.options.debug == '1':
cfg.defines += ['DEBUG', '_DEBUG']
cxx.defines += ['DEBUG', '_DEBUG']
if cxx.behavior == 'gcc':
cfg.cflags += ['-g3']
cxx.cflags += ['-g3']
elif cxx.behavior == 'msvc':
cfg.cflags += ['/Od', '/RTC1']
cxx.cflags += ['/Od', '/RTC1']
# This needs to be after our optimization flags which could otherwise disable it.
if cxx.name == 'msvc':
if cxx.family == 'msvc':
# Don't omit the frame pointer.
cfg.cflags += ['/Oy-']
cxx.cflags += ['/Oy-']
# Platform-specifics
if builder.target_platform == 'linux':
cfg.defines += ['_LINUX', 'POSIX', '_FILE_OFFSET_BITS=64']
if cxx.name == 'gcc':
cfg.linkflags += ['-static-libgcc']
elif cxx.name == 'clang':
cfg.linkflags += ['-lgcc_eh']
elif builder.target_platform == 'mac':
cfg.defines += ['OSX', '_OSX', 'POSIX']
cfg.cflags += ['-mmacosx-version-min=10.5']
cfg.linkflags += [
if builder.target.platform == 'linux':
cxx.defines += ['_LINUX', 'POSIX', '_FILE_OFFSET_BITS=64']
if cxx.family == 'gcc':
cxx.linkflags += ['-static-libgcc']
elif cxx.family == 'clang':
cxx.linkflags += ['-lgcc_eh']
elif builder.target.platform == 'mac':
cxx.defines += ['OSX', '_OSX', 'POSIX']
cxx.cflags += ['-mmacosx-version-min=10.5']
cxx.linkflags += [
'-mmacosx-version-min=10.5',
'-arch', 'i386',
'-lstdc++',
]
elif builder.target_platform == 'windows':
cfg.defines += ['WIN32', '_WINDOWS']
elif builder.target.platform == 'windows':
cxx.defines += ['WIN32', '_WINDOWS']
# Finish up.
cfg.defines += [ 'MMS_USE_VERSIONLIB' ]
cfg.includes += [
cxx.defines += [ 'MMS_USE_VERSIONLIB' ]
cxx.includes += [
os.path.join(builder.sourcePath, 'public'),
]
if self.use_auto_versioning():
cfg.defines += ['MMS_GENERATED_BUILD']
cfg.includes += [
cxx.defines += ['MMS_GENERATED_BUILD']
cxx.includes += [
os.path.join(builder.buildPath, 'includes'),
os.path.join(builder.sourcePath, 'versionlib'),
]
def HL2Compiler(self, context, sdk):
compiler = context.compiler.clone()
compiler = context.cxx.clone()
compiler.cxxincludes += [
os.path.join(context.currentSourcePath),
os.path.join(context.currentSourcePath, 'sourcehook'),
@ -270,23 +301,30 @@ class MMSConfig(object):
compiler.defines += ['SOURCE_ENGINE=' + sdk.code]
if sdk.name in ['sdk2013', 'bms'] and compiler.cxx.behavior == 'gcc':
if sdk.name in ['sdk2013', 'bms'] and compiler.like('gcc'):
# The 2013 SDK already has these in public/tier0/basetypes.h
compiler.defines.remove('stricmp=strcasecmp')
compiler.defines.remove('_stricmp=strcasecmp')
compiler.defines.remove('_snprintf=snprintf')
compiler.defines.remove('_vsnprintf=vsnprintf')
if compiler.cc.behavior == 'msvc':
compiler.defines += ['COMPILER_MSVC', 'COMPILER_MSVC32']
if compiler.family == 'msvc':
compiler.defines += ['COMPILER_MSVC']
if builder.target.arch == 'x86':
compiler.defines += ['COMPILER_MSVC32']
elif builder.target.arch == 'x86_64':
compiler.defines += ['COMPILER_MSVC64']
else:
compiler.defines += ['COMPILER_GCC']
if sdk.name == 'dota' and builder.target.arch == 'x86_64':
compiler.defines += ['X64BITS', 'PLATFORM_64BITS']
if sdk.name in ['css', 'hl2dm', 'dods', 'sdk2013', 'bms', 'tf2', 'l4d', 'nucleardawn', 'l4d2', 'dota']:
if builder.target_platform in ['linux', 'mac']:
if builder.target.platform in ['linux', 'mac']:
compiler.defines += ['NO_HOOK_MALLOC', 'NO_MALLOC_OVERRIDE']
if sdk.name == 'csgo' and builder.target_platform == 'linux':
if sdk.name == 'csgo' and builder.target.platform == 'linux':
compiler.linkflags += ['-lstdc++']
@ -296,13 +334,13 @@ class MMSConfig(object):
return compiler
def AddVersioning(self, binary):
if builder.target_platform == 'windows':
if builder.target.platform == 'windows':
binary.sources += ['version.rc']
binary.compiler.rcdefines += [
'BINARY_NAME="{0}"'.format(binary.outputFile),
'RC_COMPILE'
]
elif builder.target_platform == 'mac':
elif builder.target.platform == 'mac':
binary.compiler.postlink += [
'-compatibility_version', '1.0.0',
'-current_version', self.productVersion
@ -329,30 +367,30 @@ class MMSConfig(object):
return binary
def Library(self, context, name):
compiler = context.compiler.clone()
compiler = context.cxx.clone()
return self.LibraryBuilder(compiler, name)
def Program(self, context, name):
compiler = context.compiler.clone()
compiler = context.cxx.clone()
return self.ProgramBuilder(compiler, name)
def HL2Library(self, context, name, sdk):
compiler = self.HL2Compiler(context, sdk)
if builder.target_platform == 'linux':
if builder.target.platform == 'linux':
if sdk.name == 'episode1':
lib_folder = os.path.join(sdk.path, 'linux_sdk')
elif sdk.name in ['sdk2013', 'bms']:
lib_folder = os.path.join(sdk.path, 'lib', 'public', 'linux32')
else:
lib_folder = os.path.join(sdk.path, 'lib', 'linux')
elif builder.target_platform == 'mac':
elif builder.target.platform == 'mac':
if sdk.name in ['sdk2013', 'bms']:
lib_folder = os.path.join(sdk.path, 'lib', 'public', 'osx32')
else:
lib_folder = os.path.join(sdk.path, 'lib', 'mac')
if builder.target_platform in ['linux', 'mac']:
if builder.target.platform in ['linux', 'mac']:
if sdk.name in ['sdk2013', 'bms']:
compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'tier1.a'))]
else:
@ -364,7 +402,7 @@ class MMSConfig(object):
binary = self.LibraryBuilder(compiler, name)
dynamic_libs = []
if builder.target_platform == 'linux':
if builder.target.platform == 'linux':
compiler.linkflags[0:0] = ['-lm']
if sdk.name in ['css', 'hl2dm', 'dods', 'tf2', 'sdk2013', 'bms', 'nucleardawn', 'l4d2', 'insurgency']:
dynamic_libs = ['libtier0_srv.so', 'libvstdlib_srv.so']
@ -372,15 +410,18 @@ class MMSConfig(object):
dynamic_libs = ['libtier0.so', 'libvstdlib.so']
else:
dynamic_libs = ['tier0_i486.so', 'vstdlib_i486.so']
elif builder.target_platform == 'mac':
elif builder.target.platform == 'mac':
binary.compiler.linkflags.append('-liconv')
dynamic_libs = ['libtier0.dylib', 'libvstdlib.dylib']
elif builder.target_platform == 'windows':
elif builder.target.platform == 'windows':
libs = ['tier0', 'tier1', 'vstdlib']
if sdk.name in ['swarm', 'blade', 'insurgency', 'csgo', 'dota']:
libs.append('interfaces')
for lib in libs:
lib_path = os.path.join(sdk.path, 'lib', 'public', lib) + '.lib'
if builder.target.arch == 'x86':
lib_path = os.path.join(sdk.path, 'lib', 'public', lib) + '.lib'
elif builder.target.arch == 'x86_64':
lib_path = os.path.join(sdk.path, 'lib', 'public', 'win64', lib) + '.lib'
binary.compiler.linkflags.append(binary.Dep(lib_path))
for library in dynamic_libs:
@ -404,18 +445,18 @@ MMS.detectSDKs()
MMS.configure()
if MMS.use_auto_versioning():
MMS.generated_headers = builder.RunScript(
MMS.generated_headers = builder.Build(
'support/buildbot/Versioning',
{ 'MMS': MMS }
)
MMS.versionlib = builder.RunScript(
MMS.versionlib = builder.Build(
'versionlib/AMBuildScript',
{ 'MMS': MMS }
)
BuildScripts = [
'loader/AMBuilder',
'core/AMBuilder',
'loader/AMBuilder',
'core/AMBuilder',
]
if getattr(builder.options, 'enable_tests', False):
BuildScripts += [
@ -427,7 +468,7 @@ if builder.backend == 'amb2':
'support/buildbot/PackageScript',
]
builder.RunBuildScripts(BuildScripts, { 'MMS': MMS })
builder.Build(BuildScripts, { 'MMS': MMS })
if builder.options.breakpad_dump:
builder.RunScript('support/buildbot/BreakpadSymbols', { 'MMS': MMS })

View File

@ -12,19 +12,23 @@ except:
sys.stderr.write('http://www.alliedmods.net/ambuild\n')
sys.exit(1)
run = run.PrepareBuild(sourcePath=sys.path[0])
run.default_build_folder = 'obj-' + run.target_platform
run.options.add_option('--hl2sdk-root', type=str, dest='hl2sdk_root', default=None,
def make_objdir_name(p):
return 'obj-linux-' + p.target_arch
parser = run.BuildParser(sourcePath=sys.path[0], api='2.1')
parser.default_arch = 'x86'
parser.default_build_folder = make_objdir_name
parser.options.add_option('--hl2sdk-root', type=str, dest='hl2sdk_root', default=None,
help='Root search folder for HL2SDKs')
run.options.add_option('--enable-debug', action='store_const', const='1', dest='debug',
parser.options.add_option('--enable-debug', action='store_const', const='1', dest='debug',
help='Enable debugging symbols')
run.options.add_option('--enable-optimize', action='store_const', const='1', dest='opt',
parser.options.add_option('--enable-optimize', action='store_const', const='1', dest='opt',
help='Enable optimization')
run.options.add_option('-s', '--sdks', default='all', dest='sdks',
parser.options.add_option('-s', '--sdks', default='all', dest='sdks',
help='Build against specified SDKs; valid args are "all", "present", or '
'comma-delimited list of engine names (default: %default)')
run.options.add_option('--enable-tests', default=False, dest='enable_tests', action='store_true',
parser.options.add_option('--enable-tests', default=False, dest='enable_tests', action='store_true',
help='Build tests.')
run.options.add_option('--breakpad-dump', action='store_true', dest='breakpad_dump',
parser.options.add_option('--breakpad-dump', action='store_true', dest='breakpad_dump',
default=False, help='Dump and upload breakpad symbols')
run.Configure()
parser.Configure()

View File

@ -16,7 +16,6 @@ for sdk_name in MMS.sdks:
'provider/console.cpp',
'provider/provider_ep2.cpp',
'sourcehook/sourcehook.cpp',
'sourcehook/sourcehook_hookmangen.cpp',
'sourcehook/sourcehook_impl_chookidman.cpp',
'sourcehook/sourcehook_impl_chookmaninfo.cpp',
'sourcehook/sourcehook_impl_cproto.cpp',
@ -24,5 +23,9 @@ for sdk_name in MMS.sdks:
'gamedll_bridge.cpp',
'vsp_bridge.cpp'
]
# Source2 hack. TODO: check this more deterministically, "are we doing an x64 build?"
if builder.target.arch == 'x86':
binary.sources += ['sourcehook/sourcehook_hookmangen.cpp']
nodes = builder.Add(binary)
MMS.binaries += [nodes]

View File

@ -39,7 +39,6 @@
#if defined META_NO_HL2SDK
class CGlobalVars;
class IServerPluginCallbacks;
struct edict_t;
class ConCommandBase;
#else
@ -56,6 +55,8 @@ class ConCommandBase;
typedef void* (*CreateInterfaceFn)(const char *pName, int *pReturnCode);
class IServerPluginCallbacks;
namespace SourceMM
{
class ISmmPlugin;

View File

@ -39,6 +39,8 @@
#include <ISmmAPI.h>
#include <ISmmPluginExt.h>
class IServerPluginCallbacks;
// Interface return status, binary-compatible with HL2SDK's IFACE_OK and IFACE_FAILED.
enum
{

View File

@ -63,7 +63,11 @@ public:
SourceHook::MemFuncInfo mfi;
mfi.isVirtual = false;
#if SOURCE_ENGINE == SE_DOTA
SourceHook::GetFuncInfo(&IServerGameDLL::Shutdown, mfi);
#else
SourceHook::GetFuncInfo(&IServerGameDLL::DLLShutdown, mfi);
#endif
assert(mfi.isVirtual);
assert(mfi.vtbloffs == 0);
assert(mfi.thisptroffs == 0);

View File

@ -37,6 +37,9 @@
#if defined __linux__
#include <sys/stat.h>
#endif
#if SOURCE_ENGINE == SE_DOTA
#include <iserver.h>
#endif
using namespace SourceMM;
using namespace SourceHook;
@ -47,6 +50,28 @@ using namespace SourceHook::Impl;
* @file sourcemm.cpp
*/
#if SOURCE_ENGINE == SE_DOTA
// Hack to make hook decl compile when only having forward decl in header.
// (we have class structure but it requires protobuf which we don't want to include here)
class GameSessionConfiguration_t { };
SH_DECL_MANUALHOOK3_void(SGD_StartupServer, 0, 0, 0, const GameSessionConfiguration_t &, ISource2WorldSession *, const char *);
SH_DECL_MANUALHOOK2_void(SGD_Init, 0, 0, 0, GameSessionConfiguration_t *, const char *);
SH_DECL_MANUALHOOK3(SGD_StartChangeLevel, 0, 0, 0, CUtlVector<INetworkGameClient *> *, const char *, const char *, void *);
SH_DECL_MANUALHOOK5_void(SGD_SwitchToLoop, 0, 0, 0, const char *, KeyValues *, uint32, const char *, bool);
static void
Handler_SwitchToLoop(const char *, KeyValues *, uint32, const char *, bool);
static void
Handler_StartupServer_Post(const GameSessionConfiguration_t &, ISource2WorldSession *, const char *);
static void
Handler_Init(GameSessionConfiguration_t *, const char *);
static CUtlVector<INetworkGameClient *> *
Handler_StartChangeLevel(const char *, const char *, void *);
#else
SH_DECL_MANUALHOOK0(SGD_GameInit, 0, 0, 0, bool);
SH_DECL_MANUALHOOK6(SGD_LevelInit, 0, 0, 0, bool, const char *, const char *, const char *, const char *, bool, bool);
SH_DECL_MANUALHOOK0_void(SGD_LevelShutdown, 0, 0, 0);
@ -64,6 +89,7 @@ Handler_LevelInit(char const *pMapName,
static bool
Handler_GameInit();
#endif
static void
InitializeVSP();
@ -98,8 +124,9 @@ static ConVar *mm_basedir = NULL;
static CreateInterfaceFn engine_factory = NULL;
static CreateInterfaceFn physics_factory = NULL;
static CreateInterfaceFn filesystem_factory = NULL;
static CGlobalVars *gpGlobals = NULL;
#if !defined( __amd64__ )
static CHookManagerAutoGen g_SH_HookManagerAutoGen(&g_SourceHook);
#endif
static META_RES last_meta_res;
static IServerPluginCallbacks *vsp_callbacks = NULL;
static bool were_plugins_loaded = false;
@ -157,6 +184,23 @@ mm_InitializeForLoad()
*/
in_first_level = true;
#if SOURCE_ENGINE == SE_DOTA
SourceHook::MemFuncInfo info;
if (!provider->GetHookInfo(ProvidedHook_StartupServer, &info))
{
provider->DisplayError("Metamod:Source could not find a valid hook for INetworkServerService::StartupServer");
}
SH_MANUALHOOK_RECONFIGURE(SGD_StartupServer, info.vtblindex, info.vtbloffs, info.thisptroffs);
SH_ADD_MANUALHOOK(SGD_StartupServer, netservice, SH_STATIC(Handler_StartupServer_Post), true);
if (!provider->GetHookInfo(ProvidedHook_SwitchToLoop, &info))
{
provider->DisplayError("Metamod:Source could not find a valid hook for IEngineServiceMgr::SwitchToLoop");
}
SH_MANUALHOOK_RECONFIGURE(SGD_SwitchToLoop, info.vtblindex, info.vtbloffs, info.thisptroffs);
SH_ADD_MANUALHOOK(SGD_SwitchToLoop, enginesvcmgr, SH_STATIC(Handler_SwitchToLoop), false);
#else
SourceHook::MemFuncInfo info;
if (!provider->GetHookInfo(ProvidedHook_GameInit, &info))
@ -179,6 +223,7 @@ mm_InitializeForLoad()
}
SH_MANUALHOOK_RECONFIGURE(SGD_LevelShutdown, info.vtblindex, info.vtbloffs, info.thisptroffs);
SH_ADD_MANUALHOOK_STATICFUNC(SGD_LevelShutdown, server, Handler_LevelShutdown, true);
#endif
}
bool
@ -469,27 +514,6 @@ mm_InitializeGlobals(CreateInterfaceFn engineFactory,
provider->Notify_DLLInit_Pre(engineFactory, gamedll_info.factory);
}
static bool
Handler_GameInit()
{
if (is_game_init)
return true;
if (vsp_load_requested)
InitializeVSP();
if (g_bIsVspBridged && !were_plugins_loaded)
{
DoInitialPluginLoads();
g_PluginMngr.SetAllLoaded();
were_plugins_loaded = true;
}
is_game_init = true;
RETURN_META_VALUE(MRES_IGNORED, true);
}
void
mm_UnloadMetamod()
{
@ -502,8 +526,35 @@ mm_UnloadMetamod()
}
static void
Handler_LevelShutdown(void)
mm_HandleGameInit()
{
if (is_game_init)
return;
#if SOURCE_ENGINE == SE_DOTA
DevMsg("MMS: GameInit\n");
#endif
if (vsp_load_requested)
InitializeVSP();
if (g_bIsVspBridged && !were_plugins_loaded)
{
DoInitialPluginLoads();
g_PluginMngr.SetAllLoaded();
were_plugins_loaded = true;
}
is_game_init = true;
}
static void
mm_HandleLevelShutdown()
{
#if SOURCE_ENGINE == SE_DOTA
DevMsg("MMS: LevelShutdown\n");
#endif
if (g_bIsVspBridged && !were_plugins_loaded)
{
DoInitialPluginLoads();
@ -534,6 +585,96 @@ Handler_LevelShutdown(void)
}
ITER_EVENT(OnLevelShutdown, ());
}
static void
mm_HandleLevelInit(char const *pMapName,
char const *pMapEntities,
char const *pOldLevel,
char const *pLandmarkName,
bool loadGame,
bool background)
{
#if SOURCE_ENGINE == SE_DOTA
DevMsg("MMS: LevelInit\n");
#endif
ITER_EVENT(OnLevelInit, (pMapName, pMapEntities, pOldLevel, pLandmarkName, loadGame, background));
}
#include <utlbuffer.h>
#if SOURCE_ENGINE == SE_DOTA
static void
Handler_SwitchToLoop(const char *pszLoopName, KeyValues *pKV, uint32 nId, const char *pszUnk, bool bUnk)
{
if (strcmp(pszLoopName, "levelload") == 0)
{
mm_HandleGameInit();
}
RETURN_META(MRES_IGNORED);
}
static void
Handler_StartupServer_Post(const GameSessionConfiguration_t &config, ISource2WorldSession *, const char *)
{
static bool bGameServerHooked = false;
if (!bGameServerHooked)
{
INetworkGameServer *netserver = (META_IFACEPTR(INetworkServerService))->GetIGameServer();
SourceHook::MemFuncInfo info;
if (!provider->GetHookInfo(ProvidedHook_Init, &info))
{
provider->DisplayError("Metamod:Source could not find a valid hook for INetworkGameServer::Init");
}
SH_MANUALHOOK_RECONFIGURE(SGD_Init, info.vtblindex, info.vtbloffs, info.thisptroffs);
SH_ADD_MANUALVPHOOK(SGD_Init, netserver, SH_STATIC(Handler_Init), false);
if (!provider->GetHookInfo(ProvidedHook_StartChangeLevel, &info))
{
provider->DisplayError("Metamod:Source could not find a valid hook for INetworkGameServer::StartChangeLevel");
}
SH_MANUALHOOK_RECONFIGURE(SGD_StartChangeLevel, info.vtblindex, info.vtbloffs, info.thisptroffs);
SH_ADD_MANUALVPHOOK(SGD_StartChangeLevel, netserver, SH_STATIC(Handler_StartChangeLevel), false);
bGameServerHooked = true;
}
RETURN_META(MRES_IGNORED);
}
static void
Handler_Init(GameSessionConfiguration_t *pConfig, const char *pszMapName)
{
static char szLastMap[260] = "";
mm_HandleLevelInit(pszMapName, "", szLastMap, "", false, false);
UTIL_Format(szLastMap, sizeof(szLastMap), "%s", pszMapName);
RETURN_META(MRES_IGNORED);
}
static CUtlVector<INetworkGameClient *> *
Handler_StartChangeLevel(const char *, const char *, void *)
{
mm_HandleLevelShutdown();
RETURN_META_VALUE(MRES_IGNORED, nullptr);
}
#else
static bool
Handler_GameInit()
{
mm_HandleGameInit();
RETURN_META_VALUE(MRES_IGNORED, true);
}
static void
Handler_LevelShutdown(void)
{
mm_HandleLevelShutdown();
RETURN_META(MRES_IGNORED);
}
@ -550,6 +691,7 @@ Handler_LevelInit(char const *pMapName,
RETURN_META_VALUE(MRES_IGNORED, false);
}
#endif
void MetamodSource::LogMsg(ISmmPlugin *pl, const char *msg, ...)
{
@ -855,11 +997,19 @@ void *MetamodSource::MetaFactory(const char *iface, int *ret, PluginId *id)
}
else if (strcmp(iface, MMIFACE_SH_HOOKMANAUTOGEN) == 0)
{
#if defined( __amd64__ )
if (ret)
{
*ret = META_IFACE_FAILED;
}
return nullptr;
#else
if (ret)
{
*ret = META_IFACE_OK;
}
return static_cast<void *>(static_cast<SourceHook::IHookManagerAutoGen *>(&g_SH_HookManagerAutoGen));
#endif
}
CPluginManager::CPlugin *pl;

View File

@ -100,10 +100,6 @@ bool GetFileOfAddress(void *pAddr, char *buffer, size_t maxlength);
typedef unsigned __int32 uint32_t;
#elif defined __GNUC__
#include <stdint.h>
#if !__GLIBC_HAVE_LONG_LONG
typedef long long int64_t;
typedef unsigned long long uint64_t;
#endif
#endif
#if !defined __linux__ && !defined __APPLE__

View File

@ -37,9 +37,16 @@ namespace SourceMM
enum ProvidedHooks
{
#if SOURCE_ENGINE == SE_DOTA
ProvidedHook_StartChangeLevel = 0,
ProvidedHook_Init = 1,
ProvidedHook_StartupServer = 2,
ProvidedHook_SwitchToLoop = 3,
#else
ProvidedHook_LevelInit = 0, /**< IServerGameDLL::LevelInit */
ProvidedHook_LevelShutdown = 1, /**< IServerGameDLL::LevelShutdown */
ProvidedHook_GameInit = 4, /**< IServerGameDLL::GameInit */
#endif
};
/**

View File

@ -38,6 +38,18 @@
#include "metamod_console.h"
#include <filesystem.h>
#include "metamod.h"
#include <tier1/KeyValues.h>
#if SOURCE_ENGINE == SE_DOTA
#include <iserver.h>
#endif
#if SOURCE_ENGINE == SE_DOTA && defined( _WIN32 )
SH_DECL_HOOK1(ISource2ServerConfig, AllowDedicatedServers, const, 0, bool, EUniverse);
bool BaseProvider::AllowDedicatedServers(EUniverse universe) const
{
RETURN_META_VALUE(MRES_SUPERCEDE, true);
}
#endif
/* Types */
typedef void (*CONPRINTF_FUNC)(const char *, ...);
@ -63,14 +75,18 @@ DLL_IMPORT ICommandLine *CommandLine();
void CacheUserMessages();
bool KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL);
void Detour_Error(const tchar *pMsg, ...);
#if SOURCE_ENGINE == SE_DOTA
void ClientCommand(CEntityIndex index, const CCommand &args);
void LocalCommand_Meta(const CCommandContext &context, const CCommand &args);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
void ClientCommand(edict_t *pEdict, const CCommand &args);
void LocalCommand_Meta(const CCommand &args);
#else
void ClientCommand(edict_t *pEdict);
#endif
#if SOURCE_ENGINE >= SE_ORANGEBOX
void LocalCommand_Meta(const CCommand &args);
#else
void LocalCommand_Meta();
#endif
@ -85,8 +101,14 @@ static bool g_bOriginalEngine = false;
ICvar *icvar = NULL;
IFileSystem *baseFs = NULL;
IServerGameDLL *server = NULL;
#if SOURCE_ENGINE == SE_DOTA
static ISource2ServerConfig *serverconfig = NULL;
INetworkServerService *netservice = NULL;
IEngineServiceMgr *enginesvcmgr = NULL;
#endif
IVEngineServer *engine = NULL;
IServerGameClients *gameclients = NULL;
CGlobalVars *gpGlobals = NULL;
IMetamodSourceProvider *provider = &g_Ep1Provider;
ConCommand meta_local_cmd("meta", LocalCommand_Meta, "Metamod:Source control options");
@ -129,6 +151,12 @@ void BaseProvider::Notify_DLLInit_Pre(CreateInterfaceFn engineFactory,
DisplayError("Could not find IVEngineServer! Metamod cannot load.");
return;
}
#if SOURCE_ENGINE == SE_DOTA
gpGlobals = engine->GetServerGlobals();
serverconfig = (ISource2ServerConfig *) ((serverFactory) (INTERFACEVERSION_SERVERCONFIG, NULL));
netservice = (INetworkServerService *) ((engineFactory) (NETWORKSERVERSERVICE_INTERFACE_VERSION, NULL));
enginesvcmgr = (IEngineServiceMgr *) ((engineFactory) (ENGINESERVICEMGR_INTERFACE_VERSION, NULL));
#endif
#if SOURCE_ENGINE >= SE_ORANGEBOX
icvar = (ICvar *)((engineFactory)(CVAR_INTERFACE_VERSION, NULL));
#else
@ -140,12 +168,15 @@ void BaseProvider::Notify_DLLInit_Pre(CreateInterfaceFn engineFactory,
return;
}
#if SOURCE_ENGINE == SE_DOTA
gameclients = (IServerGameClients *)(serverFactory(INTERFACEVERSION_SERVERGAMECLIENTS, NULL));
#else
if ((gameclients = (IServerGameClients *)(serverFactory("ServerGameClients003", NULL)))
== NULL)
{
gameclients = (IServerGameClients *)(serverFactory("ServerGameClients004", NULL));
}
#endif
baseFs = (IFileSystem *)((engineFactory)(FILESYSTEM_INTERFACE_VERSION, NULL));
if (baseFs == NULL)
@ -153,6 +184,41 @@ void BaseProvider::Notify_DLLInit_Pre(CreateInterfaceFn engineFactory,
mm_LogMessage("Unable to find \"%s\": .vdf files will not be parsed", FILESYSTEM_INTERFACE_VERSION);
}
#if SOURCE_ENGINE == SE_DOTA
// Since we have to be added as a Game path (cannot add GameBin directly), we
// automatically get added to other paths as well, including having the MM:S
// dir become the default write path for logs and more. We can fix some of these.
char searchPath[260];
baseFs->GetSearchPath("GAME", (GetSearchPathTypes_t)0, searchPath, sizeof(searchPath));
for (size_t i = 0; i < sizeof(searchPath); ++i)
{
if (searchPath[i] == ';')
{
searchPath[i] = '\0';
break;
}
}
baseFs->RemoveSearchPath(searchPath, "GAME");
// TODO: figure out why these calls get ignored and path remains
//baseFs->RemoveSearchPath(searchPath, "CONTENT");
//baseFs->RemoveSearchPath(searchPath, "SHADER_SOURCE");
//baseFs->RemoveSearchPath(searchPath, "SHADER_SOURCE_MOD");
baseFs->RemoveSearchPaths("DEFAULT_WRITE_PATH");
baseFs->GetSearchPath("GAME", (GetSearchPathTypes_t)0, searchPath, sizeof(searchPath));
for (size_t i = 0; i < sizeof(searchPath); ++i)
{
if (searchPath[i] == ';')
{
searchPath[i] = '\0';
break;
}
}
baseFs->AddSearchPath(searchPath, "DEFAULT_WRITE_PATH");
#endif
#if SOURCE_ENGINE >= SE_ORANGEBOX
g_pCVar = icvar;
#endif
@ -179,6 +245,10 @@ void BaseProvider::Notify_DLLInit_Pre(CreateInterfaceFn engineFactory,
{
SH_ADD_HOOK_STATICFUNC(IServerGameClients, ClientCommand, gameclients, ClientCommand, false);
}
#if SOURCE_ENGINE == SE_DOTA && defined( _WIN32 )
SH_ADD_VPHOOK(ISource2ServerConfig, AllowDedicatedServers, serverconfig, SH_MEMBER(this, &BaseProvider::AllowDedicatedServers), false);
#endif
}
void BaseProvider::Notify_DLLShutdown_Pre()
@ -201,7 +271,7 @@ bool BaseProvider::IsRemotePrintingAvailable()
void BaseProvider::ClientConsolePrint(edict_t *pEdict, const char *message)
{
#if SOURCE_ENGINE == SE_DOTA
int client = (int)(pEdict - g_Metamod.GetCGlobals()->pEdicts);
int client = (int)(pEdict - gpGlobals->pEdicts);
engine->ClientPrintf(client, message);
#else
engine->ClientPrintf(pEdict, message);
@ -284,6 +354,31 @@ bool BaseProvider::LogMessage(const char *buffer)
bool BaseProvider::GetHookInfo(ProvidedHooks hook, SourceHook::MemFuncInfo *pInfo)
{
#if SOURCE_ENGINE == SE_DOTA
SourceHook::MemFuncInfo mfi = {true, -1, 0, 0};
switch (hook)
{
case ProvidedHook_StartupServer:
SourceHook::GetFuncInfo(&INetworkServerService::StartupServer, mfi);
break;
case ProvidedHook_StartChangeLevel:
SourceHook::GetFuncInfo(&INetworkGameServer::StartChangeLevel, mfi);
break;
case ProvidedHook_Init:
SourceHook::GetFuncInfo(&INetworkGameServer::Init, mfi);
break;
case ProvidedHook_SwitchToLoop:
SourceHook::GetFuncInfo(&IEngineServiceMgr::SwitchToLoop, mfi);
break;
default:
return false;
}
*pInfo = mfi;
return (mfi.thisptroffs >= 0);
#else
SourceHook::MemFuncInfo mfi = {true, -1, 0, 0};
if (hook == ProvidedHook_LevelInit)
@ -302,6 +397,7 @@ bool BaseProvider::GetHookInfo(ProvidedHooks hook, SourceHook::MemFuncInfo *pInf
*pInfo = mfi;
return (mfi.thisptroffs >= 0);
#endif
}
void BaseProvider::DisplayError(const char *fmt, ...)
@ -391,7 +487,11 @@ void BaseProvider::GetGamePath(char *pszBuffer, int len)
const char *BaseProvider::GetGameDescription()
{
#if SOURCE_ENGINE == SE_DOTA
return serverconfig->GetGameDescription();
#else
return server->GetGameDescription();
#endif
}
int BaseProvider::DetermineSourceEngine()
@ -618,11 +718,7 @@ public:
};
#endif
#if SOURCE_ENGINE == SE_DOTA
void LocalCommand_Meta(const CCommandContext &context, const CCommand &args)
{
GlobCommand cmd(&args);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
#if SOURCE_ENGINE >= SE_ORANGEBOX
void LocalCommand_Meta(const CCommand &args)
{
GlobCommand cmd(&args);

View File

@ -32,7 +32,9 @@
#endif
#include <sourcehook.h>
#include <sh_memfuncinfo.h>
#if SOURCE_ENGINE != SE_DOTA
#include <iserverplugin.h>
#endif
#include "ISmmAPI.h"
#include "metamod_provider.h"
#include "metamod_oslink.h"
@ -44,6 +46,8 @@
using namespace SourceMM;
using namespace SourceHook;
class INetworkGameServer;
class BaseProvider : public IMetamodSourceProvider
{
public:
@ -78,12 +82,20 @@ public:
virtual int DetermineSourceEngine();
virtual bool ProcessVDF(const char *file, char path[], size_t path_len, char alias[], size_t alias_len);
virtual const char *GetEngineDescription() const;
#if SOURCE_ENGINE == SE_DOTA && defined( _WIN32 )
bool AllowDedicatedServers(EUniverse universe) const;
#endif
};
extern IVEngineServer *engine;
extern IServerGameDLL *server;
extern IServerGameClients *gameclients;
extern ICvar *icvar;
extern CGlobalVars *gpGlobals;
#if SOURCE_ENGINE == SE_DOTA
extern INetworkServerService *netservice;
extern IEngineServiceMgr *enginesvcmgr;
#endif
#endif //_INCLUDE_METAMOD_SOURCE_BASE_PROVIDER_H_

View File

@ -125,6 +125,11 @@ namespace SourceHook
addr += 2;
ok = true;
}
else if (addr[0] == 0x48 && addr[1] == 0x8B && addr[2] == 0x01)
{
addr += 3;
ok = true;
}
if (!ok)
return -1;
@ -132,11 +137,11 @@ namespace SourceHook
{
if (*addr == 0x60)
{
return *++addr / 4;
return *++addr / SH_PTRSIZE;
}
else if (*addr == 0xA0)
{
return *((unsigned int*)++addr) / 4;
return *((unsigned int*)++addr) / SH_PTRSIZE;
}
else if (*addr == 0x20)
return 0;

View File

@ -18,6 +18,11 @@
using namespace std;
bool g_Verbose;
struct Unloader : public SourceHook::Impl::UnloadListener
{
void ReadyToUnload(SourceHook::Plugin) { }
} g_UnloadListener;
#define DECL_TEST(x) bool Test##x(std::string &error);
#define DO_TEST(x) \
@ -73,7 +78,9 @@ int main(int argc, char *argv[])
DO_TEST(RefRet);
DO_TEST(VPHooks);
DO_TEST(CPageAlloc);
#if !defined( _M_AMD64 ) && !defined( __amd64__ ) // TODO: Fix for 64-bit
DO_TEST(HookManGen);
#endif
DO_TEST(OddThunks);
cout << endl << "----" << endl << "Passed: " << passed << endl << "Failed: " << failed << endl;

View File

@ -0,0 +1,40 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test.vcxproj", "{456BBA64-FF14-4292-8443-3BA79E4D84CC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug_NoDebugRuntimeLib|Win32 = Debug_NoDebugRuntimeLib|Win32
Debug_NoDebugRuntimeLib|x64 = Debug_NoDebugRuntimeLib|x64
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
DebugOpt|Win32 = DebugOpt|Win32
DebugOpt|x64 = DebugOpt|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{456BBA64-FF14-4292-8443-3BA79E4D84CC}.Debug_NoDebugRuntimeLib|Win32.ActiveCfg = Debug_NoDebugRuntimeLib|Win32
{456BBA64-FF14-4292-8443-3BA79E4D84CC}.Debug_NoDebugRuntimeLib|Win32.Build.0 = Debug_NoDebugRuntimeLib|Win32
{456BBA64-FF14-4292-8443-3BA79E4D84CC}.Debug_NoDebugRuntimeLib|x64.ActiveCfg = Debug_NoDebugRuntimeLib|x64
{456BBA64-FF14-4292-8443-3BA79E4D84CC}.Debug_NoDebugRuntimeLib|x64.Build.0 = Debug_NoDebugRuntimeLib|x64
{456BBA64-FF14-4292-8443-3BA79E4D84CC}.Debug|Win32.ActiveCfg = Debug|Win32
{456BBA64-FF14-4292-8443-3BA79E4D84CC}.Debug|Win32.Build.0 = Debug|Win32
{456BBA64-FF14-4292-8443-3BA79E4D84CC}.Debug|x64.ActiveCfg = Debug|x64
{456BBA64-FF14-4292-8443-3BA79E4D84CC}.Debug|x64.Build.0 = Debug|x64
{456BBA64-FF14-4292-8443-3BA79E4D84CC}.DebugOpt|Win32.ActiveCfg = DebugOpt|Win32
{456BBA64-FF14-4292-8443-3BA79E4D84CC}.DebugOpt|Win32.Build.0 = DebugOpt|Win32
{456BBA64-FF14-4292-8443-3BA79E4D84CC}.DebugOpt|x64.ActiveCfg = DebugOpt|x64
{456BBA64-FF14-4292-8443-3BA79E4D84CC}.DebugOpt|x64.Build.0 = DebugOpt|x64
{456BBA64-FF14-4292-8443-3BA79E4D84CC}.Release|Win32.ActiveCfg = Release|Win32
{456BBA64-FF14-4292-8443-3BA79E4D84CC}.Release|Win32.Build.0 = Release|Win32
{456BBA64-FF14-4292-8443-3BA79E4D84CC}.Release|x64.ActiveCfg = Release|x64
{456BBA64-FF14-4292-8443-3BA79E4D84CC}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,461 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="DebugOpt|Win32">
<Configuration>DebugOpt</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="DebugOpt|x64">
<Configuration>DebugOpt</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug_NoDebugRuntimeLib|Win32">
<Configuration>Debug_NoDebugRuntimeLib</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug_NoDebugRuntimeLib|x64">
<Configuration>Debug_NoDebugRuntimeLib</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{456BBA64-FF14-4292-8443-3BA79E4D84CC}</ProjectGuid>
<RootNamespace>test</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug_NoDebugRuntimeLib|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug_NoDebugRuntimeLib|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugOpt|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugOpt|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug_NoDebugRuntimeLib|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug_NoDebugRuntimeLib|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='DebugOpt|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='DebugOpt|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>12.0.30501.0</_ProjectFileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>Debug\</OutDir>
<IntDir>Debug\</IntDir>
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>Release\</OutDir>
<IntDir>Release\</IntDir>
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugOpt|Win32'">
<OutDir>DebugOpt\</OutDir>
<IntDir>DebugOpt\</IntDir>
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugOpt|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug_NoDebugRuntimeLib|Win32'">
<OutDir>Debug_NoDebugRuntimeLib\</OutDir>
<IntDir>Debug_NoDebugRuntimeLib\</IntDir>
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug_NoDebugRuntimeLib|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>../..;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;SH_DEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader />
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
</ClCompile>
<Link>
<OutputFile>$(OutDir)test.exe</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)test.pdb</ProgramDatabaseFile>
<SubSystem>Console</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention />
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<Optimization>Disabled</Optimization>
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>../..;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;SH_DEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<OutputFile>$(OutDir)test.exe</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)test.pdb</ProgramDatabaseFile>
<SubSystem>Console</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>Full</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<AdditionalIncludeDirectories>../..;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader />
<BrowseInformation />
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<OutputFile>$(OutDir)test.exe</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<GenerateMapFile>true</GenerateMapFile>
<MapExports>true</MapExports>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention />
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<Optimization>Full</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<AdditionalIncludeDirectories>../..;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader>
</PrecompiledHeader>
<BrowseInformation>
</BrowseInformation>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<OutputFile>$(OutDir)test.exe</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<GenerateMapFile>true</GenerateMapFile>
<MapExports>true</MapExports>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugOpt|Win32'">
<ClCompile>
<Optimization>Full</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<IntrinsicFunctions>false</IntrinsicFunctions>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader />
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<OutputFile>$(OutDir)test.exe</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)test.pdb</ProgramDatabaseFile>
<SubSystem>Console</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention />
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugOpt|x64'">
<ClCompile>
<Optimization>Full</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<IntrinsicFunctions>false</IntrinsicFunctions>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<OutputFile>$(OutDir)test.exe</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)test.pdb</ProgramDatabaseFile>
<SubSystem>Console</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug_NoDebugRuntimeLib|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>../..;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild>
<ExceptionHandling>Sync</ExceptionHandling>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader />
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
</ClCompile>
<Link>
<OutputFile>$(OutDir)test.exe</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)test.pdb</ProgramDatabaseFile>
<SubSystem>Console</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention />
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug_NoDebugRuntimeLib|x64'">
<ClCompile>
<Optimization>Disabled</Optimization>
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>../..;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<ExceptionHandling>Sync</ExceptionHandling>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<OutputFile>$(OutDir)test.exe</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)test.pdb</ProgramDatabaseFile>
<SubSystem>Console</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\sourcehook.cpp" />
<ClCompile Include="..\..\sourcehook_hookmangen.cpp" />
<ClCompile Include="..\..\sourcehook_impl_chookidman.cpp" />
<ClCompile Include="..\..\sourcehook_impl_chookmaninfo.cpp" />
<ClCompile Include="..\..\sourcehook_impl_cproto.cpp" />
<ClCompile Include="..\..\sourcehook_impl_cvfnptr.cpp" />
<ClCompile Include="..\main.cpp" />
<ClCompile Include="..\test1.cpp" />
<ClCompile Include="..\test2.cpp" />
<ClCompile Include="..\test3.cpp" />
<ClCompile Include="..\test4.cpp" />
<ClCompile Include="..\testbail.cpp" />
<ClCompile Include="..\testbail2.cpp" />
<ClCompile Include="..\testhookmangen.cpp" />
<ClCompile Include="..\testlist.cpp" />
<ClCompile Include="..\testmanual.cpp">
<PreprocessToFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</PreprocessToFile>
<PreprocessToFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</PreprocessToFile>
<PreprocessSuppressLineNumbers Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</PreprocessSuppressLineNumbers>
<PreprocessSuppressLineNumbers Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</PreprocessSuppressLineNumbers>
</ClCompile>
<ClCompile Include="..\testmulti.cpp" />
<ClCompile Include="..\testoddthunks.cpp" />
<ClCompile Include="..\testrecall.cpp" />
<ClCompile Include="..\testreentr.cpp" />
<ClCompile Include="..\testref.cpp" />
<ClCompile Include="..\testrefret.cpp" />
<ClCompile Include="..\testvphooks.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\generate\FastDelegate.hxx" />
<ClInclude Include="..\..\generate\sh_memfuncinfo.hxx" />
<CustomBuild Include="..\..\generate\sourcehook.hxx">
<Command Condition="'$(Configuration)|$(Platform)'=='Debug_NoDebugRuntimeLib|Win32'">echo on
pushd ..\..\generate
shworker.exe iter sourcehook.hxx sourcehook.h 16
copy sourcehook.h ..\sourcehook.h
popd
</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug_NoDebugRuntimeLib|x64'">echo on
pushd ..\..\generate
shworker.exe iter sourcehook.hxx sourcehook.h 16
copy sourcehook.h ..\sourcehook.h
popd
</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug_NoDebugRuntimeLib|Win32'">..\..\sourcehook.h;%(Outputs)</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug_NoDebugRuntimeLib|x64'">..\..\sourcehook.h;%(Outputs)</Outputs>
</CustomBuild>
<ClInclude Include="..\..\sh_list.h" />
<ClInclude Include="..\..\sh_memfuncinfo.h" />
<ClInclude Include="..\..\sh_memory.h" />
<ClInclude Include="..\..\sh_pagealloc.h" />
<ClInclude Include="..\..\sh_stack.h" />
<ClInclude Include="..\..\sh_string.h" />
<ClInclude Include="..\..\sh_tinyhash.h" />
<ClInclude Include="..\..\sh_vector.h" />
<ClInclude Include="..\..\sourcehook.h" />
<ClInclude Include="..\..\sourcehook_hookmangen.h" />
<ClInclude Include="..\..\sourcehook_hookmangen_x86.h" />
<ClInclude Include="..\..\sourcehook_impl.h" />
<ClInclude Include="..\..\sourcehook_impl_chook.h" />
<ClInclude Include="..\..\sourcehook_impl_chookidman.h" />
<ClInclude Include="..\..\sourcehook_impl_chookmaninfo.h" />
<ClInclude Include="..\..\sourcehook_impl_ciface.h" />
<ClInclude Include="..\..\sourcehook_impl_cleanuptask.h" />
<ClInclude Include="..\..\sourcehook_impl_cproto.h" />
<ClInclude Include="..\..\sourcehook_impl_cvfnptr.h" />
<ClInclude Include="..\..\sourcehook_pibuilder.h" />
<ClInclude Include="..\sourcehook_test.h" />
<ClInclude Include="..\testbail.h" />
<ClInclude Include="..\testevents.h" />
<ClInclude Include="..\testhookmangen.h" />
<ClInclude Include="..\testhookmangen.hxx" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,191 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{097d3bc9-e1f2-4054-93f3-b12d28409a01}</UniqueIdentifier>
<Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm</Extensions>
</Filter>
<Filter Include="Source Files\SourceHook">
<UniqueIdentifier>{c1c8bd55-c7ae-46fc-a115-e490b5068b5c}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\TestTools">
<UniqueIdentifier>{17326c78-c7e4-456b-b9df-019e07ca478f}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{c15408a4-1aa9-485e-916b-c4eeaddeeee2}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc</Extensions>
</Filter>
<Filter Include="Header Files\TestTools">
<UniqueIdentifier>{be31706d-65c6-4945-b7be-84dcbbcde2e7}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\SourceHook">
<UniqueIdentifier>{75eb6b5b-331a-4eba-b0b2-687c273e2746}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\SourceHook\generate">
<UniqueIdentifier>{1efd71b2-ab96-4217-ab65-dbc369ec623f}</UniqueIdentifier>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{d4f35fc6-e668-474b-82af-0771f32cde7f}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\sourcehook.cpp">
<Filter>Source Files\SourceHook</Filter>
</ClCompile>
<ClCompile Include="..\..\sourcehook_hookmangen.cpp">
<Filter>Source Files\SourceHook</Filter>
</ClCompile>
<ClCompile Include="..\..\sourcehook_impl_chookidman.cpp">
<Filter>Source Files\SourceHook</Filter>
</ClCompile>
<ClCompile Include="..\..\sourcehook_impl_chookmaninfo.cpp">
<Filter>Source Files\SourceHook</Filter>
</ClCompile>
<ClCompile Include="..\..\sourcehook_impl_cproto.cpp">
<Filter>Source Files\SourceHook</Filter>
</ClCompile>
<ClCompile Include="..\..\sourcehook_impl_cvfnptr.cpp">
<Filter>Source Files\SourceHook</Filter>
</ClCompile>
<ClCompile Include="..\main.cpp">
<Filter>Source Files\TestTools</Filter>
</ClCompile>
<ClCompile Include="..\test1.cpp">
<Filter>Source Files\TestTools</Filter>
</ClCompile>
<ClCompile Include="..\test2.cpp">
<Filter>Source Files\TestTools</Filter>
</ClCompile>
<ClCompile Include="..\test3.cpp">
<Filter>Source Files\TestTools</Filter>
</ClCompile>
<ClCompile Include="..\test4.cpp">
<Filter>Source Files\TestTools</Filter>
</ClCompile>
<ClCompile Include="..\testbail.cpp">
<Filter>Source Files\TestTools</Filter>
</ClCompile>
<ClCompile Include="..\testbail2.cpp">
<Filter>Source Files\TestTools</Filter>
</ClCompile>
<ClCompile Include="..\testhookmangen.cpp">
<Filter>Source Files\TestTools</Filter>
</ClCompile>
<ClCompile Include="..\testlist.cpp">
<Filter>Source Files\TestTools</Filter>
</ClCompile>
<ClCompile Include="..\testmanual.cpp">
<Filter>Source Files\TestTools</Filter>
</ClCompile>
<ClCompile Include="..\testmulti.cpp">
<Filter>Source Files\TestTools</Filter>
</ClCompile>
<ClCompile Include="..\testoddthunks.cpp">
<Filter>Source Files\TestTools</Filter>
</ClCompile>
<ClCompile Include="..\testrecall.cpp">
<Filter>Source Files\TestTools</Filter>
</ClCompile>
<ClCompile Include="..\testreentr.cpp">
<Filter>Source Files\TestTools</Filter>
</ClCompile>
<ClCompile Include="..\testref.cpp">
<Filter>Source Files\TestTools</Filter>
</ClCompile>
<ClCompile Include="..\testrefret.cpp">
<Filter>Source Files\TestTools</Filter>
</ClCompile>
<ClCompile Include="..\testvphooks.cpp">
<Filter>Source Files\TestTools</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\testbail.h">
<Filter>Header Files\TestTools</Filter>
</ClInclude>
<ClInclude Include="..\testevents.h">
<Filter>Header Files\TestTools</Filter>
</ClInclude>
<ClInclude Include="..\testhookmangen.h">
<Filter>Header Files\TestTools</Filter>
</ClInclude>
<ClInclude Include="..\..\sh_list.h">
<Filter>Header Files\SourceHook</Filter>
</ClInclude>
<ClInclude Include="..\..\sh_memfuncinfo.h">
<Filter>Header Files\SourceHook</Filter>
</ClInclude>
<ClInclude Include="..\..\sh_memory.h">
<Filter>Header Files\SourceHook</Filter>
</ClInclude>
<ClInclude Include="..\..\sh_pagealloc.h">
<Filter>Header Files\SourceHook</Filter>
</ClInclude>
<ClInclude Include="..\..\sh_stack.h">
<Filter>Header Files\SourceHook</Filter>
</ClInclude>
<ClInclude Include="..\..\sh_string.h">
<Filter>Header Files\SourceHook</Filter>
</ClInclude>
<ClInclude Include="..\..\sh_tinyhash.h">
<Filter>Header Files\SourceHook</Filter>
</ClInclude>
<ClInclude Include="..\..\sh_vector.h">
<Filter>Header Files\SourceHook</Filter>
</ClInclude>
<ClInclude Include="..\..\sourcehook.h">
<Filter>Header Files\SourceHook</Filter>
</ClInclude>
<ClInclude Include="..\..\sourcehook_hookmangen.h">
<Filter>Header Files\SourceHook</Filter>
</ClInclude>
<ClInclude Include="..\..\sourcehook_hookmangen_x86.h">
<Filter>Header Files\SourceHook</Filter>
</ClInclude>
<ClInclude Include="..\..\sourcehook_impl.h">
<Filter>Header Files\SourceHook</Filter>
</ClInclude>
<ClInclude Include="..\..\sourcehook_impl_chook.h">
<Filter>Header Files\SourceHook</Filter>
</ClInclude>
<ClInclude Include="..\..\sourcehook_impl_chookidman.h">
<Filter>Header Files\SourceHook</Filter>
</ClInclude>
<ClInclude Include="..\..\sourcehook_impl_chookmaninfo.h">
<Filter>Header Files\SourceHook</Filter>
</ClInclude>
<ClInclude Include="..\..\sourcehook_impl_ciface.h">
<Filter>Header Files\SourceHook</Filter>
</ClInclude>
<ClInclude Include="..\..\sourcehook_impl_cleanuptask.h">
<Filter>Header Files\SourceHook</Filter>
</ClInclude>
<ClInclude Include="..\..\sourcehook_impl_cproto.h">
<Filter>Header Files\SourceHook</Filter>
</ClInclude>
<ClInclude Include="..\..\sourcehook_impl_cvfnptr.h">
<Filter>Header Files\SourceHook</Filter>
</ClInclude>
<ClInclude Include="..\..\sourcehook_pibuilder.h">
<Filter>Header Files\SourceHook</Filter>
</ClInclude>
<ClInclude Include="..\sourcehook_test.h">
<Filter>Header Files\SourceHook</Filter>
</ClInclude>
<ClInclude Include="..\..\generate\FastDelegate.hxx">
<Filter>Header Files\SourceHook\generate</Filter>
</ClInclude>
<ClInclude Include="..\..\generate\sh_memfuncinfo.hxx">
<Filter>Header Files\SourceHook\generate</Filter>
</ClInclude>
<ClInclude Include="..\testhookmangen.hxx">
<Filter>Header Files\SourceHook\generate</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="..\..\generate\sourcehook.hxx">
<Filter>Header Files\SourceHook\generate</Filter>
</CustomBuild>
</ItemGroup>
</Project>

View File

@ -98,13 +98,30 @@ namespace
// Now generate the jump code
g_ThunkAllocator.SetRW(g_OddThunkMemory);
*(base + 0) = 0xE9; // offset jump, immediate operand
ptrdiff_t *offsetAddr = reinterpret_cast<ptrdiff_t*>(base + 1);
// destination = src + offset + 5
// <=> offset = destination - src - 5
*offsetAddr =
(reinterpret_cast<unsigned char*>(origEntry) - base) - 5;
ptrdiff_t offset = reinterpret_cast<unsigned char*>(origEntry) - base - 5;
if (offset >= INT_MIN && offset <= INT_MAX)
{
*(base + 0) = 0xE9; // offset jump, immediate operand
ptrdiff_t *offsetAddr = reinterpret_cast<ptrdiff_t*>(base + 1);
*offsetAddr = offset;
}
else
{
// mov rax, origEntry
*(base + 0) = 0x48;
*(base + 1) = 0xB8;
void **offsetAddr = reinterpret_cast<void**>(reinterpret_cast<char*>(base) + 2);
*offsetAddr = origEntry;
// jmp rax
*(base + 10) = 0xFF;
*(base + 11) = 0xE0;
}
g_ThunkAllocator.SetRE(g_OddThunkMemory);

View File

@ -34,7 +34,7 @@
#include <sh_string.h>
#include "provider/provider_ep2.h"
#if SOURCE_ENGINE == SE_DOTA || SOURCE_ENGINE == SE_SOURCE2
#if SOURCE_ENGINE == SE_DOTA
SH_DECL_HOOK2_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommandContext &, const CCommand &);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
SH_DECL_HOOK1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
@ -164,11 +164,14 @@ public:
virtual void Unload()
{
// Source2 doesn't have the Error function (nor VSP support).
#if SOURCE_ENGINE != SE_DOTA
if (g_bIsTryingToUnload)
{
Error("Metamod:Source cannot be unloaded from VSP mode. Use \"meta unload\" to unload specific plugins.\n");
return;
}
#endif
if (g_plugin_unload != NULL)
{
SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, g_plugin_unload, InterceptPluginUnloads, false);

View File

@ -11,12 +11,17 @@ def configure_library(name, linux_defines):
'utility.cpp',
]
if builder.target_platform == 'linux':
if builder.target.platform == 'linux':
binary.compiler.defines += linux_defines
nodes = builder.Add(binary)
MMS.binaries += [nodes]
configure_library('server', ['LIB_PREFIX="lib"', 'LIB_SUFFIX=".so"'])
if builder.target_platform == 'linux':
libname = 'server'
if builder.target.platform == 'linux' and builder.target.arch == 'x86_64':
libname = 'libserver'
configure_library(libname, ['LIB_PREFIX="lib"', 'LIB_SUFFIX=".so"'])
if builder.target.platform == 'linux' and builder.target.arch == 'x86':
configure_library('server_i486', ['LIB_PREFIX=""', 'LIB_SUFFIX="_i486.so"'])

View File

@ -2,7 +2,7 @@
* vim: set ts=4 sw=4 tw=99 noet :
* ======================================================
* Metamod:Source
* Copyright (C) 2004-2009 AlliedModders LLC and authors.
* Copyright (C) 2004-2015 AlliedModders LLC and authors.
* All rights reserved.
* ======================================================
*
@ -36,6 +36,7 @@
#include "gamedll.h"
class IServerGameDLL;
class ISource2ServerConfig;
#define MAX_GAMEDLL_PATHS 10
@ -47,17 +48,40 @@ static void *gamedll_libs[MAX_GAMEDLL_PATHS];
static unsigned int gamedll_path_count = 0;
static void *gamedll_lib = NULL;
static IServerGameDLL *gamedll_iface = NULL;
static ISource2ServerConfig *config_iface = NULL;
static QueryValveInterface gamedll_qvi = NULL;
static int gamedll_version = 0;
static int isgd_shutdown_index = -1;
#if defined _WIN32
static int is2sc_allowdedi_index = 21;
#endif
static char mm_path[PLATFORM_MAX_PATH];
static bool g_is_source2 = false;
#if defined _WIN32
#define SERVER_NAME "server.dll"
#if defined _WIN64
#define PLATFORM_NAME "win64"
#else
#define PLATFORM_NAME "win32"
#endif
#elif defined __APPLE__
#define SERVER_NAME "server.dylib"
#if defined __amd64__
#define PLATFORM_NAME "osx64"
#else
#define PLATFORM_NAME "osx32"
#endif
#elif defined __linux__
#define SERVER_NAME "server" LIB_SUFFIX
#if defined __amd64__
// hackhack - source2 uses libserver as name on POSIX, but source1 x64 does not
// (but source1 x64 is also client-only right now so what-ev)
#define SERVER_NAME "libserver" LIB_SUFFIX
#define PLATFORM_NAME "linuxsteamrt64"
#else
#define SERVER_NAME "server" LIB_SUFFIX
#define PLATFORM_NAME "linuxsteamrt32"
#endif
#endif
static bool
@ -78,7 +102,7 @@ mm_DetectGameInformation()
return false;
}
if (!mm_ResolvePath(game_name, game_path, sizeof(game_path)))
if (!mm_ResolvePath(game_name, game_path, sizeof(game_path), g_is_source2))
{
mm_LogFatal("Could not resolve path: %s", game_name);
return false;
@ -87,11 +111,21 @@ mm_DetectGameInformation()
FILE *fp;
char gameinfo_path[PLATFORM_MAX_PATH];
bool is_source2 = false;
mm_PathFormat(gameinfo_path, sizeof(gameinfo_path), "%s/gameinfo.txt", game_path);
if ((fp = fopen(gameinfo_path, "rt")) == NULL)
{
mm_LogFatal("Could not read file: %s", gameinfo_path);
return false;
// Try Source2 gameinfo
mm_PathFormat(gameinfo_path, sizeof(gameinfo_path), "%s/gameinfo.gi", game_path);
if ((fp = fopen(gameinfo_path, "rt")) == NULL)
{
mm_LogFatal("Could not read file: %s", gameinfo_path);
return false;
}
else
{
is_source2 = true;
}
}
char temp_path[PLATFORM_MAX_PATH];
@ -131,12 +165,14 @@ mm_DetectGameInformation()
lptr = cur_path;
}
const char *pRelPath = is_source2 ? "../../" : "";
const char *pOSDir = is_source2 ? PLATFORM_NAME "/" : "";
if (stricmp(key, "GameBin") == 0)
mm_PathFormat(temp_path, sizeof(temp_path), "%s/%s/" SERVER_NAME, lptr, ptr);
mm_PathFormat(temp_path, sizeof(temp_path), "%s/%s%s/%s" SERVER_NAME, lptr, pRelPath, ptr, pOSDir);
else if (!ptr[0])
mm_PathFormat(temp_path, sizeof(temp_path), "%s/bin/" SERVER_NAME, lptr);
mm_PathFormat(temp_path, sizeof(temp_path), "%s/%sbin/%s" SERVER_NAME, lptr, pRelPath, pOSDir);
else
mm_PathFormat(temp_path, sizeof(temp_path), "%s/%s/bin/" SERVER_NAME, lptr, ptr);
mm_PathFormat(temp_path, sizeof(temp_path), "%s/%s%s/bin/%s" SERVER_NAME, lptr, pRelPath, ptr, pOSDir);
if (mm_PathCmp(mm_path, temp_path))
continue;
@ -174,7 +210,7 @@ mm_DetectGameInformation()
if (gamedll_path_count == 0)
{
mm_LogFatal("Could not detect any valid game paths in gameinfo.txt");
mm_LogFatal("Could not detect any valid game paths in gameinfo file");
return false;
}
@ -198,13 +234,216 @@ mm_PatchDllInit(bool patch);
static void
mm_PatchDllShutdown();
#if defined _WIN32
static void
mm_PatchAllowDedicated(bool patch);
#endif
static void
mm_PatchConnect(bool patch);
static void *isgd_orig_init = NULL;
static void *isgd_orig_shutdown = NULL;
#if defined _WIN32
static void *is2sc_orig_allowdedi = NULL;
#endif
static void *is2sc_orig_connect = NULL;
class VEmptyClass
{
};
gamedll_bridge_info g_bridge_info;
// Source2 - Rough start order
// CreateInterfaceFn (IS2SC) - hook Connect and AllowDedicatedServer
// IS2SC::Connect - save factory pointer. return orig. remove hook.
// IS2SC::AllowDedicatedServer - return true. remove hook.
// CreateInterfaceFn (IS2S) - hook Init and Shutdown
// IS2S::Init - do same as old ISGD::DLLInit, including core load. return orig. remove hook.
// IS2S::Shutdown - <-- this
enum InitReturnVal_t
{
INIT_FAILED = 0,
INIT_OK,
INIT_LAST_VAL,
};
class ISource2ServerConfig
{
public:
virtual bool Connect(QueryValveInterface factory)
{
g_bridge_info.engineFactory = factory;
g_bridge_info.fsFactory = factory;
g_bridge_info.physicsFactory = factory;
/* Call the original */
bool result;
{
union
{
bool(VEmptyClass::*mfpnew)(QueryValveInterface factory);
#if defined _WIN32
void *addr;
} u;
u.addr = is2sc_orig_connect;
#else
struct
{
void *addr;
intptr_t adjustor;
} s;
} u;
u.s.addr = is2sc_orig_connect;
u.s.adjustor = 0;
#endif
result = (((VEmptyClass *) config_iface)->*u.mfpnew)(factory);
}
mm_PatchConnect(false);
return result;
}
#if defined _WIN32
virtual bool AllowDedicatedServers(int universe) const
{
mm_PatchAllowDedicated(false);
return true;
}
#endif
};
class ISource2Server
{
public:
virtual bool Connect(QueryValveInterface factory) { return true; }
virtual void Disconnect() {}
virtual void *QueryInterface(const char *pInterfaceName) { return nullptr; }
virtual InitReturnVal_t Init()
{
mm_backend = MMBackend_DOTA;
char error[255];
if (!mm_LoadMetamodLibrary(mm_backend, error, sizeof(error)))
{
mm_LogFatal("Detected engine %d but could not load: %s", mm_backend, error);
}
else
{
typedef IGameDllBridge *(*GetGameDllBridge)();
GetGameDllBridge get_bridge = (GetGameDllBridge)mm_GetProcAddress("GetGameDllBridge");
if (get_bridge == NULL)
{
mm_UnloadMetamodLibrary();
mm_LogFatal("Detected engine %d but could not find GetGameDllBridge callback", mm_backend);
}
else
{
gamedll_bridge = get_bridge();
}
}
if (gamedll_bridge)
{
g_bridge_info.pGlobals = nullptr;// pGlobals;
g_bridge_info.dllVersion = gamedll_version;
g_bridge_info.isgd = gamedll_iface;
g_bridge_info.gsFactory = gamedll_qvi;
g_bridge_info.vsp_listener_path = mm_path;
strcpy(error, "Unknown error");
if (!gamedll_bridge->DLLInit_Pre(&g_bridge_info, error, sizeof(error)))
{
gamedll_bridge = NULL;
mm_UnloadMetamodLibrary();
mm_LogFatal("Unknown error loading Metamod for engine %d: %s", mm_backend, error);
}
}
/* Call the original */
InitReturnVal_t result;
{
union
{
InitReturnVal_t(VEmptyClass::*mfpnew)();
#if defined _WIN32
void *addr;
} u;
u.addr = isgd_orig_init;
#else
struct
{
void *addr;
intptr_t adjustor;
} s;
} u;
u.s.addr = isgd_orig_init;
u.s.adjustor = 0;
#endif
result = (((VEmptyClass *)gamedll_iface)->*u.mfpnew)();
}
/**
* :TODO: possible logic hole here, what happens if the gamedll REALLY returns false?
* I'm pretty sure we'll die horribly.
*/
if (!result)
{
gamedll_bridge->Unload();
mm_UnloadMetamodLibrary();
gamedll_bridge = NULL;
}
else if (gamedll_bridge != NULL)
{
gamedll_bridge->DLLInit_Post(&isgd_shutdown_index);
assert(isgd_shutdown_index != -1);
mm_PatchDllShutdown();
}
mm_PatchDllInit(false);
return result;
}
virtual void Shutdown()
{
gamedll_bridge->Unload();
gamedll_bridge = NULL;
mm_UnloadMetamodLibrary();
/* Call original function */
{
union
{
void (VEmptyClass::*mfpnew)();
#if defined _WIN32
void *addr;
} u;
u.addr = isgd_orig_shutdown;
#else
struct
{
void *addr;
intptr_t adjustor;
} s;
} u;
u.s.addr = isgd_orig_shutdown;
u.s.adjustor = 0;
#endif
(((VEmptyClass *)gamedll_iface)->*u.mfpnew)();
}
mm_UnloadLibrary(gamedll_lib);
gamedll_lib = NULL;
}
};
class IServerGameDLL
{
public:
@ -244,19 +483,17 @@ public:
if (gamedll_bridge)
{
gamedll_bridge_info info;
info.engineFactory = (QueryValveInterface)engineFactory;
info.physicsFactory = (QueryValveInterface)physicsFactory;
info.fsFactory = (QueryValveInterface)fileSystemFactory;
info.pGlobals = pGlobals;
info.dllVersion = gamedll_version;
info.isgd = gamedll_iface;
info.gsFactory = gamedll_qvi;
info.vsp_listener_path = mm_path;
g_bridge_info.engineFactory = (QueryValveInterface)engineFactory;
g_bridge_info.physicsFactory = (QueryValveInterface)physicsFactory;
g_bridge_info.fsFactory = (QueryValveInterface)fileSystemFactory;
g_bridge_info.pGlobals = pGlobals;
g_bridge_info.dllVersion = gamedll_version;
g_bridge_info.isgd = gamedll_iface;
g_bridge_info.gsFactory = gamedll_qvi;
g_bridge_info.vsp_listener_path = mm_path;
strcpy(error, "Unknown error");
if (!gamedll_bridge->DLLInit_Pre(&info, error, sizeof(error)))
if (!gamedll_bridge->DLLInit_Pre(&g_bridge_info, error, sizeof(error)))
{
gamedll_bridge = NULL;
mm_UnloadMetamodLibrary();
@ -350,6 +587,8 @@ public:
};
static IServerGameDLL isgd_thunk;
static ISource2Server is2s_thunk;
static ISource2ServerConfig is2sc_thunk;
static void
mm_PatchDllInit(bool patch)
@ -358,13 +597,27 @@ mm_PatchDllInit(bool patch)
void **vtable_dest;
SourceHook::MemFuncInfo mfp;
SourceHook::GetFuncInfo(&IServerGameDLL::DLLInit, mfp);
if (g_is_source2)
{
SourceHook::GetFuncInfo(&ISource2Server::Init, mfp);
}
else
{
SourceHook::GetFuncInfo(&IServerGameDLL::DLLInit, mfp);
}
assert(mfp.isVirtual);
assert(mfp.thisptroffs == 0);
assert(mfp.vtbloffs == 0);
vtable_src = (void **)*(void **)&isgd_thunk;
if (g_is_source2)
{
vtable_src = (void **)*(void **)&is2s_thunk;
}
else
{
vtable_src = (void **)*(void **)&isgd_thunk;
}
vtable_dest = (void **)*(void **)gamedll_iface;
SourceHook::SetMemAccess(&vtable_dest[mfp.vtblindex],
@ -393,33 +646,169 @@ mm_PatchDllShutdown()
SourceHook::MemFuncInfo mfp;
mfp.isVirtual = false;
SourceHook::GetFuncInfo(&IServerGameDLL::DLLShutdown, mfp);
if (g_is_source2)
{
SourceHook::GetFuncInfo(&ISource2Server::Shutdown, mfp);
}
else
{
SourceHook::GetFuncInfo(&IServerGameDLL::DLLShutdown, mfp);
}
assert(mfp.isVirtual);
assert(mfp.thisptroffs == 0);
assert(mfp.vtbloffs == 0);
vtable_src = (void **)*(void **)&isgd_thunk;
if (g_is_source2)
{
vtable_src = (void **)*(void **)&is2s_thunk;
}
else
{
vtable_src = (void **)*(void **)&isgd_thunk;
}
vtable_dest = (void **)*(void **)gamedll_iface;
isgd_orig_shutdown = vtable_dest[isgd_shutdown_index];
vtable_dest[isgd_shutdown_index] = vtable_src[mfp.vtblindex];
}
#if defined _WIN32
static void
mm_PrepForGameLoad()
mm_PatchAllowDedicated(bool patch)
{
mm_PatchDllInit(true);
void **vtable_src;
void **vtable_dest;
SourceHook::MemFuncInfo mfp;
SourceHook::GetFuncInfo(&ISource2ServerConfig::AllowDedicatedServers, mfp);
assert(mfp.isVirtual);
assert(mfp.thisptroffs == 0);
assert(mfp.vtbloffs == 0);
vtable_src = (void **) *(void **) &is2sc_thunk;
vtable_dest = (void **) *(void **) config_iface;
SourceHook::SetMemAccess(&vtable_dest[is2sc_allowdedi_index],
sizeof(void*),
SH_MEM_READ | SH_MEM_WRITE | SH_MEM_EXEC);
if (patch)
{
assert(is2sc_orig_allowdedi == NULL);
is2sc_orig_allowdedi = vtable_dest[is2sc_allowdedi_index];
vtable_dest[is2sc_allowdedi_index] = vtable_src[mfp.vtblindex];
}
else
{
assert(is2sc_orig_allowdedi != NULL);
vtable_dest[is2sc_allowdedi_index] = is2sc_orig_allowdedi;
is2sc_orig_allowdedi = NULL;
}
}
#endif
static void
mm_PatchConnect(bool patch)
{
void **vtable_src;
void **vtable_dest;
SourceHook::MemFuncInfo mfp;
SourceHook::GetFuncInfo(&ISource2ServerConfig::Connect, mfp);
assert(mfp.isVirtual);
assert(mfp.thisptroffs == 0);
assert(mfp.vtbloffs == 0);
vtable_src = (void **) *(void **) &is2sc_thunk;
vtable_dest = (void **) *(void **) config_iface;
SourceHook::SetMemAccess(&vtable_dest[mfp.vtblindex],
sizeof(void*),
SH_MEM_READ | SH_MEM_WRITE | SH_MEM_EXEC);
if (patch)
{
assert(is2sc_orig_connect == NULL);
is2sc_orig_connect = vtable_dest[mfp.vtblindex];
vtable_dest[mfp.vtblindex] = vtable_src[mfp.vtblindex];
}
else
{
assert(is2sc_orig_connect != NULL);
vtable_dest[mfp.vtblindex] = is2sc_orig_connect;
is2sc_orig_connect = NULL;
}
}
void *
mm_GameDllRequest(const char *name, int *ret)
{
if (gamedll_lib != NULL && gamedll_bridge == NULL)
if (strncmp(name, "Source2ServerConfig", 19) == 0)
{
return gamedll_qvi(name, ret);
}
g_is_source2 = true;
if (!mm_DetectGameInformation())
{
if (ret != NULL)
*ret = 1;
return NULL;
}
if (strncmp(name, "ServerGameDLL", 13) == 0)
void *lib;
char error[255];
void *ptr = NULL;
QueryValveInterface qvi;
for (unsigned int i = 0; i < gamedll_path_count; i++)
{
if (gamedll_libs[i] == NULL)
{
lib = mm_LoadLibrary(gamedll_paths[i], error, sizeof(error));
if (lib == NULL)
continue;
gamedll_libs[i] = lib;
}
lib = gamedll_libs[i];
qvi = (QueryValveInterface)mm_GetLibAddress(lib, "CreateInterface");
if (qvi == NULL)
continue;
ptr = qvi(name, ret);
if (ptr != NULL)
{
gamedll_libs[i] = NULL;
break;
}
}
if (ptr != NULL)
{
mm_FreeCachedLibraries();
gamedll_lib = lib;
config_iface = (ISource2ServerConfig *) ptr;
gamedll_qvi = qvi;
mm_PatchConnect(true);
#if defined _WIN32
mm_PatchAllowDedicated(true);
#endif
if (ret != NULL)
*ret = 0;
return ptr;
}
}
else if (strncmp(name, "Source2Server0", 14) == 0)
{
gamedll_iface = (IServerGameDLL *)gamedll_qvi(name, ret);
gamedll_version = atoi(&name[13]);
mm_PatchDllInit(true);
if (ret != NULL)
*ret = 0;
return gamedll_iface;
}
else if (strncmp(name, "ServerGameDLL", 13) == 0)
{
if (!mm_DetectGameInformation())
{
@ -460,13 +849,17 @@ mm_GameDllRequest(const char *name, int *ret)
gamedll_iface = (IServerGameDLL *)ptr;
gamedll_qvi = qvi;
gamedll_version = atoi(&name[13]);
mm_PrepForGameLoad();
mm_PatchDllInit(true);
if (ret != NULL)
*ret = 0;
return ptr;
}
}
else if (gamedll_lib != NULL && gamedll_bridge == NULL)
{
return gamedll_qvi(name, ret);
}
else if (game_info_detected == 0)
{
mm_LogFatal("Received interface request too early: %s", name);

View File

@ -2,7 +2,7 @@
* vim: set ts=4 sw=4 tw=99 noet :
* ======================================================
* Metamod:Source
* Copyright (C) 2004-2010 AlliedModders LLC and authors.
* Copyright (C) 2004-2015 AlliedModders LLC and authors.
* All rights reserved.
* ======================================================
*
@ -114,7 +114,12 @@ mm_LoadMetamodLibrary(MetamodBackend backend, char *buffer, size_t maxlength)
return false;
len = strlen(mm_path);
temp_len = strlen("server" LIBRARY_EXT);
const char *pLastSlash = strrchr(mm_path, PATH_SEP_CHAR);
if (!pLastSlash)
return false;
temp_len = strlen(&pLastSlash[1]);
if (len < temp_len)
return false;
@ -193,6 +198,7 @@ void
mm_GetGameName(char *buffer, size_t size)
{
buffer[0] = '\0';
bool bHasDedicated = false;
#if defined _WIN32
static char game[128];
@ -202,15 +208,18 @@ mm_GetGameName(char *buffer, size_t size)
LPWSTR *wargv = CommandLineToArgvW(pCmdLine, &argc);
for (int i = 0; i < argc; ++i)
{
if (wcscmp(wargv[i], L"-game") != 0)
continue;
if (wcscmp(wargv[i], L"-game") == 0)
{
if (++i >= argc)
break;
if (++i >= argc)
break;
wcstombs(buffer, wargv[i], size);
buffer[size-1] = '\0';
break;
wcstombs(buffer, wargv[i], size);
buffer[size-1] = '\0';
}
else if (wcscmp(wargv[i], L"-dedicated") == 0)
{
bHasDedicated = true;
}
}
LocalFree(wargv);
@ -220,15 +229,18 @@ mm_GetGameName(char *buffer, size_t size)
char **argv = *_NSGetArgv();
for (int i = 0; i < argc; ++i)
{
if (strcmp(argv[i], "-game") != 0)
continue;
if (strcmp(argv[i], "-game") == 0)
{
if (++i >= argc)
break;
if (++i >= argc)
break;
strncpy(buffer, argv[i], size);
buffer[size-1] = '\0';
break;
strncpy(buffer, argv[i], size);
buffer[size-1] = '\0';
}
else if (strcmp(argv[i], "-dedicated") == 0)
{
bHasDedicated = true;
}
}
#elif defined __linux__
@ -245,13 +257,17 @@ mm_GetGameName(char *buffer, size_t size)
{
strncpy(buffer, arg, size);
buffer[size-1] = '\0';
break;
bNextIsGame = false;
}
if (strcmp(arg, "-game") == 0)
{
bNextIsGame = true;
}
else if (strcmp(arg, "-dedicated") == 0)
{
bHasDedicated = true;
}
}
free(arg);
@ -263,18 +279,26 @@ mm_GetGameName(char *buffer, size_t size)
if (buffer[0] == 0)
{
strncpy(buffer, ".", size);
// HackHackHack - Different engines have different defaults if -game isn't specified
// we only use this for game detection, and not even in all cases. Old behavior was to
// give back ".", which was only really accurate for Dark Messiah. We'll add a special
// case for Source2 / Dota as well, since it only supports gameinfo loading, which relies
// on accuracy here more than VSP loading.
if (bHasDedicated)
{
strncpy(buffer, "dota", size);
}
else
{
strncpy(buffer, ".", size);
}
}
}
MetamodBackend
mm_DetermineBackend(QueryValveInterface engineFactory, QueryValveInterface serverFactory, const char *game_name)
{
if (engineFactory("VEngineServer024", NULL) != NULL)
{
return MMBackend_DOTA;
}
else if (engineFactory("VEngineServer023", NULL) != NULL)
if (engineFactory("VEngineServer023", NULL) != NULL)
{
if (engineFactory("EngineTraceServer004", NULL) == NULL)
{

View File

@ -2,7 +2,7 @@
* vim: set ts=4 sw=4 tw=99 noet :
* ======================================================
* Metamod:Source
* Copyright (C) 2004-2009 AlliedModders LLC and authors.
* Copyright (C) 2004-2015 AlliedModders LLC and authors.
* All rights reserved.
* ======================================================
*

View File

@ -2,7 +2,7 @@
* vim: set ts=4 :
* ======================================================
* Metamod:Source
* Copyright (C) 2004-2008 AlliedModders LLC and authors.
* Copyright (C) 2004-2015 AlliedModders LLC and authors.
* All rights reserved.
* ======================================================
*
@ -275,8 +275,14 @@ mm_PathCmp(const char *path1, const char *path2)
}
bool
mm_ResolvePath(const char *path, char *buffer, size_t maxlength)
mm_ResolvePath(const char *path, char *buffer, size_t maxlength, bool bSource2)
{
char tmp[PLATFORM_MAX_PATH];
if (bSource2)
{
mm_Format(tmp, sizeof(tmp), "../../%s", path);
path = tmp;
}
#if defined _WIN32
return _fullpath(buffer, path, maxlength) != NULL;
#elif defined __linux__ || defined __APPLE__

View File

@ -2,7 +2,7 @@
* vim: set ts=4 :
* ======================================================
* Metamod:Source
* Copyright (C) 2004-2008 AlliedModders LLC and authors.
* Copyright (C) 2004-2015 AlliedModders LLC and authors.
* All rights reserved.
* ======================================================
*
@ -43,7 +43,7 @@ extern void
mm_UnloadLibrary(void *lib);
extern bool
mm_ResolvePath(const char *path, char *buffer, size_t maxlength);
mm_ResolvePath(const char *path, char *buffer, size_t maxlength, bool bSource2);
extern size_t
mm_PathFormat(char *buffer, size_t len, const char *fmt, ...);

View File

@ -1,11 +1,12 @@
# vim: sts=2 ts=8 sw=2 tw=99 et ft=python:
lib = builder.compiler.StaticLibrary("version")
lib = builder.cxx.StaticLibrary("version")
lib.compiler.defines.remove('MMS_USE_VERSIONLIB')
lib.compiler.sourcedeps += MMS.generated_headers
lib.sources += [
'versionlib.cpp'
]
cmd = builder.Add(lib)
rvalue = cmd.binary