mirror of
https://github.com/rehlds/metamod-r.git
synced 2025-05-15 16:12:33 +03:00
Compare commits
No commits in common. "master" and "1.3.0.131" have entirely different histories.
45
.github/workflows/build.yml
vendored
45
.github/workflows/build.yml
vendored
@ -5,7 +5,6 @@ on:
|
|||||||
branches: [master]
|
branches: [master]
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- '**.md'
|
- '**.md'
|
||||||
- '.github/**'
|
|
||||||
|
|
||||||
pull_request:
|
pull_request:
|
||||||
types: [opened, reopened, synchronize]
|
types: [opened, reopened, synchronize]
|
||||||
@ -24,12 +23,12 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Setup MSBuild
|
- name: Setup MSBuild
|
||||||
uses: microsoft/setup-msbuild@v2
|
uses: microsoft/setup-msbuild@v1.0.2
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
@ -44,7 +43,7 @@ jobs:
|
|||||||
move msvc\${{ env.buildRelease }}\metamod.pdb publish\debug\metamod.pdb
|
move msvc\${{ env.buildRelease }}\metamod.pdb publish\debug\metamod.pdb
|
||||||
|
|
||||||
- name: Deploy artifacts
|
- name: Deploy artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: win32
|
name: win32
|
||||||
path: publish/*
|
path: publish/*
|
||||||
@ -52,28 +51,17 @@ jobs:
|
|||||||
linux:
|
linux:
|
||||||
name: 'Linux'
|
name: 'Linux'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container: debian:11-slim
|
container: s1lentq/linux86buildtools:latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Build using Intel C++ Compiler 19.0
|
||||||
run: |
|
run: |
|
||||||
dpkg --add-architecture i386
|
rm -rf build && CC=icc CXX=icpc cmake -DCMAKE_BUILD_TYPE=COMPAT_GLIBC -B build && cmake --build build -j8
|
||||||
apt-get update
|
|
||||||
apt-get install -y \
|
|
||||||
gcc-multilib g++-multilib \
|
|
||||||
build-essential \
|
|
||||||
libc6-dev libc6-dev-i386 \
|
|
||||||
git cmake rsync \
|
|
||||||
g++ gcc
|
|
||||||
|
|
||||||
- name: Build using Intel GCC Compiler
|
|
||||||
run: |
|
|
||||||
rm -rf build && cmake -DCMAKE_BUILD_TYPE=COMPAT_GLIBC -B build && cmake --build build -j8
|
|
||||||
|
|
||||||
- name: Prepare SDK
|
- name: Prepare SDK
|
||||||
run: |
|
run: |
|
||||||
@ -109,12 +97,17 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
- name: Deploy artifacts
|
- name: Deploy artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v2
|
||||||
id: upload-job
|
id: upload-job
|
||||||
with:
|
with:
|
||||||
name: linux32
|
name: linux32
|
||||||
path: publish/*
|
path: publish/*
|
||||||
|
|
||||||
|
- name: Cleanup temporary artifacts
|
||||||
|
if: success() && steps.upload-job.outcome == 'success'
|
||||||
|
run: |
|
||||||
|
rm -f appversion.h
|
||||||
|
|
||||||
publish:
|
publish:
|
||||||
name: 'Publish'
|
name: 'Publish'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@ -122,12 +115,12 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Deploying linux artifacts
|
- name: Deploying linux artifacts
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: linux32
|
name: linux32
|
||||||
|
|
||||||
- name: Deploying windows artifacts
|
- name: Deploying windows artifacts
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: win32
|
name: win32
|
||||||
|
|
||||||
@ -155,7 +148,7 @@ jobs:
|
|||||||
7z a -tzip metamod-bin-${{ env.APP_VERSION }}.zip addons/ example_plugin/ sdk/
|
7z a -tzip metamod-bin-${{ env.APP_VERSION }}.zip addons/ example_plugin/ sdk/
|
||||||
|
|
||||||
- name: Publish artifacts
|
- name: Publish artifacts
|
||||||
uses: softprops/action-gh-release@v2
|
uses: softprops/action-gh-release@v1
|
||||||
id: publish-job
|
id: publish-job
|
||||||
if: |
|
if: |
|
||||||
startsWith(github.ref, 'refs/tags/') &&
|
startsWith(github.ref, 'refs/tags/') &&
|
||||||
@ -163,3 +156,9 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
*.zip
|
*.zip
|
||||||
|
|
||||||
|
- name: Cleanup temporary artifacts
|
||||||
|
if: success() && steps.publish-job.outcome == 'success'
|
||||||
|
run: |
|
||||||
|
rm -rf addons debug example_plugin sdk
|
||||||
|
rm -f *.zip appversion.h
|
||||||
|
103
CHANGELOG.md
103
CHANGELOG.md
@ -1,103 +0,0 @@
|
|||||||
# [Metamod-r](https://github.com/rehlds/metamod-r) Changelog
|
|
||||||
|
|
||||||
**Metamod-r** is based on the original version of [Metamod](http://metamod.org/) written by _Will Day_ for Half-Life 1 with some improvements from [Jussi Kivilinna](https://github.com/jkivilin) ([Metamod-p](https://github.com/jkivilin/metamod-p)). This product contains numerous performance optimizations and cleaner code. The core was rewritten with a JIT compiler.
|
|
||||||
|
|
||||||
`*` Original changelog [here](https://github.com/Bots-United/metamod-p/blob/master/doc/Changelog).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## [`1.3.0.149`](https://github.com/rehlds/metamod-r/releases/tag/1.3.0.149) - 2024-04-23
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Fixed shutdown issue
|
|
||||||
|
|
||||||
**Full Changelog**: [1.3.0.138...1.3.0.149](https://github.com/rehlds/metamod-r/compare/1.3.0.138...1.3.0.149)
|
|
||||||
|
|
||||||
## [`1.3.0.138`](https://github.com/rehlds/metamod-r/releases/tag/1.3.0.138) - 2023-11-28
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Improved ReHLDS API initialization.
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- HLDS compatibility
|
|
||||||
- [Fixed](https://github.com/rehlds/metamod-r/commit/ec926a611f4d225bb433609bf827269ad8482618) gracefully shuts down Metamod and plugins when the game is closing (now the _restart command works properly).
|
|
||||||
|
|
||||||
**Full Changelog**: [1.3.0.131...1.3.0.138](https://github.com/rehlds/metamod-r/compare/1.3.0.131...1.3.0.138)
|
|
||||||
|
|
||||||
## [`1.3.0.131`](https://github.com/rehlds/metamod-r/releases/tag/1.3.0.131) - 2018-08-24
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Updated `C++ Intel Compiler` version `17.0` > `19.0`.
|
|
||||||
|
|
||||||
**Full Changelog**: [1.3.0.128...1.3.0.131](https://github.com/rehlds/metamod-r/compare/1.3.0.128...1.3.0.131)
|
|
||||||
|
|
||||||
## [`1.3.0.128`](https://github.com/rehlds/metamod-r/releases/tag/1.3.0.128) - 2018-08-24
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- [Fixed](https://github.com/rehlds/metamod-r/commit/0cf2f709dbeae18ca84d2fafd4481ffbba06ad0c) two bugs in `jit`.
|
|
||||||
|
|
||||||
**Full Changelog**: [1.3.0.126...1.3.0.128](https://github.com/rehlds/metamod-r/compare/1.3.0.126...1.3.0.128)
|
|
||||||
|
|
||||||
## [`1.3.0.126`](https://github.com/rehlds/metamod-r/releases/tag/1.3.0.126) - 2018-05-10
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- [Fixed](https://github.com/rehlds/metamod-r/commit/93b5bd45e279aad6a91e71504dd8deaf9896ab42) crashes in `pfnAlertMessage`.
|
|
||||||
|
|
||||||
**Full Changelog**: [1.3.0.125...1.3.0.126](https://github.com/rehlds/metamod-r/compare/1.3.0.125...1.3.0.126)
|
|
||||||
|
|
||||||
## [`1.3.0.125`](https://github.com/rehlds/metamod-r/releases/tag/1.3.0.125) - 2018-04-30
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- [Fixed](https://github.com/rehlds/metamod-r/commit/6456c5f7ec872cd98d9be964440cf96780899558#diff-f15b77cc15bf608d761260093dfe8e0d) binary names to correctly auto-detect games.
|
|
||||||
|
|
||||||
**Full Changelog**: [1.3.0.119...1.3.0.125](https://github.com/rehlds/metamod-r/compare/1.3.0.119...1.3.0.125)
|
|
||||||
|
|
||||||
## [`1.3.0.119`](https://github.com/rehlds/metamod-r/releases/tag/1.3.0.119) - 2018-03-12
|
|
||||||
|
|
||||||
### Added
|
|
||||||
- Added support for various gamedll binaries for mods.
|
|
||||||
- Added `mm_pluginsfile` option.
|
|
||||||
|
|
||||||
**Full Changelog**: [1.3.0.107...1.3.0.119](https://github.com/rehlds/metamod-r/compare/1.3.0.107...1.3.0.119)
|
|
||||||
|
|
||||||
## [`1.3.0.107`](https://github.com/rehlds/metamod-r/releases/tag/1.3.0.107) - 2018-01-29
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Fixed problems with API functions returning float.
|
|
||||||
|
|
||||||
### Added
|
|
||||||
- [Added](https://github.com/rehlds/metamod-r/commit/132cbad0099c9903123d7ff7c3e1c13344efb3c9) support for more games.
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Refactored code.
|
|
||||||
|
|
||||||
**Full Changelog**: [1.3.0.86...1.3.0.107](https://github.com/rehlds/metamod-r/compare/1.3.0.86...1.3.0.107)
|
|
||||||
|
|
||||||
## [`1.3.0.86`](https://github.com/rehlds/metamod-r/releases/tag/1.3.0.86) - 2017-11-15
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- [Fixed crash](https://github.com/rehlds/metamod-r/commit/5b7fe147231df9354a8fe29c3852bd1db8119e81) and reworked `find_memloc`.
|
|
||||||
|
|
||||||
**Full Changelog**: [1.3.0.85...1.3.0.86](https://github.com/rehlds/metamod-r/compare/1.3.0.85...1.3.0.86)
|
|
||||||
|
|
||||||
## [`1.3.0.85`](https://github.com/rehlds/metamod-r/releases/tag/1.3.0.85) - 2017-11-15
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Fixed parse plugins.ini (loads the plugins for an appropriate platform only).
|
|
||||||
- Fixed crash for meta-plugins using UPX.
|
|
||||||
|
|
||||||
**Full Changelog**: [1.3.0.84...1.3.0.85](https://github.com/rehlds/metamod-r/compare/1.3.0.84...1.3.0.85)
|
|
||||||
|
|
||||||
## [`1.3.0.84`](https://github.com/rehlds/metamod-r/releases/tag/1.3.0.84) - 2017-10-27
|
|
||||||
|
|
||||||
### Added
|
|
||||||
- First public release.
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Minor refactoring.
|
|
||||||
|
|
||||||
## `0.0.0.0` (based on `1.20p35`) - 2016-07-04
|
|
||||||
|
|
||||||
### Added
|
|
||||||
- Started `metamod-r` project by forking from `metamod-p`. Based on version `1.20p35`.
|
|
||||||
- The official changelog of the original version is missing.
|
|
27
README.md
27
README.md
@ -1,26 +1,29 @@
|
|||||||
# [Metamod-r](https://github.com/rehlds/metamod-r) [](http://isitmaintained.com/project/rehlds/metamod-r "Percentage of issues still open") [](https://github.com/rehlds/metamod-r/blob/master/LICENSE)
|
# Metamod-r [](https://github.com/theAsmodai/metamod-r/releases/latest) []() [](http://isitmaintained.com/project/theAsmodai/metamod-r "Percentage of issues still open") [](https://www.gnu.org/licenses/gpl-3.0)
|
||||||
|
|
||||||
**Metamod-r** is based on the original version of [Metamod](http://metamod.org/) written by _Will Day_ for Half-Life 1 with some improvements from [Jussi Kivilinna](https://github.com/jkivilin) ([Metamod-p](https://github.com/jkivilin/metamod-p)). This product contains a large number of performance optimizations and more pure code. The core was written using JIT compiler.
|
**Metamod-r** is based on the original version of [Metamod](http://metamod.org/) written by _Will Day_ for Half-Life 1 with some improvements from [Jussi Kivilinna](https://github.com/jkivilin) ([Metamod-p](https://github.com/jkivilin/metamod-p)). This product contains a large number of performance optimizations and more pure code. The core was written using JIT compiler.
|
||||||
|
|
||||||
**Metamod-r is recommended to be run with [ReHLDS](https://github.com/rehlds/ReHLDS) (`API 3.1+`).
|
**Metamod-r is incompatible with original `HLDS`. It's necessary to have installed [ReHLDS](https://github.com/dreamstalker/ReHLDS) (`API 3.1+`). There is no guarantee that the product will work in a different environment.**
|
||||||
There is compatible with original `HLDS`**
|
|
||||||
|
|
||||||
|HLDS | [ReHLDS](https://github.com/rehlds/ReHLDS) | OS | Download |
|
|HLDS | [ReHLDS](https://github.com/dreamstalker/ReHLDS) | OS | Download |
|
||||||
|---------| -------| --- | --- |
|
|---------| -------| --- | --- |
|
||||||
| :heavy_check_mark: | :heavy_check_mark: `API 3.1+` |  | [](https://github.com/rehlds/metamod-r/releases/latest)
|
| :x: | `API 3.1+` |  | [](https://github.com/theAsmodai/metamod-r/releases/latest)
|
||||||
|
|
||||||
[](https://metamod-r.org/)
|
[](https://metamod-r.org/)
|
||||||
[](https://github.com/rehlds/metamod-r/)
|
[](https://github.com/theAsmodai/metamod-r/)
|
||||||
[](https://github.com/rehlds/metamod-r/issues)
|
[](https://github.com/theAsmodai/metamod-r/issues)
|
||||||
[](https://github.com/rehlds/metamod-r/network)
|
[](https://github.com/theAsmodai/metamod-r/network)
|
||||||
[](https://github.com/rehlds/metamod-r/stargazers)
|
[](https://github.com/theAsmodai/metamod-r/stargazers)
|
||||||
|
|
||||||
|
|
||||||
|
Distributed under
|
||||||
|
[](https://github.com/theAsmodai/metamod-r/blob/master/LICENSE).
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
* All actual documentation in  **English** and  **Russian** languages is placed at [this link](https://github.com/rehlds/metamod-r/wiki).
|
* All actual documentation in  **English** and  **Russian** languages is placed at [this link](https://github.com/theAsmodai/metamod-r/wiki).
|
||||||
|
|
||||||
### Supported games
|
### Supported games
|
||||||
*  Actual [list of supported games](https://github.com/rehlds/metamod-r/wiki/Supported-games).
|
*  Actual [list of supported games](https://github.com/theAsmodai/metamod-r/wiki/Supported-games).
|
||||||
*  Актуальный [список поддерживаемых игр](https://github.com/rehlds/metamod-r/wiki/Поддерживаемые-игры).
|
*  Актуальный [список поддерживаемых игр](https://github.com/theAsmodai/metamod-r/wiki/Поддерживаемые-игры).
|
||||||
|
|
||||||
## Build instructions
|
## Build instructions
|
||||||
### Checking requirements
|
### Checking requirements
|
||||||
|
@ -35,7 +35,7 @@ set(CMAKE_SHARED_LIBRARY_CXX_FLAGS "")
|
|||||||
set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
|
set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
|
||||||
|
|
||||||
set(COMPILE_FLAGS "-m32 -U_FORTIFY_SOURCE")
|
set(COMPILE_FLAGS "-m32 -U_FORTIFY_SOURCE")
|
||||||
set(LINK_FLAGS "-m32")
|
set(LINK_FLAGS "-m32 -s")
|
||||||
|
|
||||||
set(COMPILE_FLAGS "${COMPILE_FLAGS} -Wall -fno-exceptions -fno-builtin -Wno-unknown-pragmas")
|
set(COMPILE_FLAGS "${COMPILE_FLAGS} -Wall -fno-exceptions -fno-builtin -Wno-unknown-pragmas")
|
||||||
|
|
||||||
@ -43,10 +43,9 @@ set(COMPILE_FLAGS "${COMPILE_FLAGS} -Wall -fno-exceptions -fno-builtin -Wno-unkn
|
|||||||
set(COMPILE_FLAGS "${COMPILE_FLAGS} -ffunction-sections -fdata-sections")
|
set(COMPILE_FLAGS "${COMPILE_FLAGS} -ffunction-sections -fdata-sections")
|
||||||
|
|
||||||
if (DEBUG)
|
if (DEBUG)
|
||||||
set(COMPILE_FLAGS "${COMPILE_FLAGS} -g3 -O0 -ggdb")
|
set(COMPILE_FLAGS "${COMPILE_FLAGS} -g3 -O3 -ggdb")
|
||||||
else()
|
else()
|
||||||
set(COMPILE_FLAGS "${COMPILE_FLAGS} -g0 -O3 -fno-stack-protector")
|
set(COMPILE_FLAGS "${COMPILE_FLAGS} -g0 -O3 -fno-stack-protector")
|
||||||
set(LINK_FLAGS "${LINK_FLAGS} -s")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Check Intel C++ compiler
|
# Check Intel C++ compiler
|
||||||
@ -150,7 +149,8 @@ target_sources(metamod PRIVATE
|
|||||||
"src/engine_api.cpp"
|
"src/engine_api.cpp"
|
||||||
"src/game_support.cpp"
|
"src/game_support.cpp"
|
||||||
"src/h_export.cpp"
|
"src/h_export.cpp"
|
||||||
"src/osdep_linkent_linux.cpp"
|
"src/linkent.cpp"
|
||||||
|
"src/linkgame.cpp"
|
||||||
"src/log_meta.cpp"
|
"src/log_meta.cpp"
|
||||||
"src/mdebug.cpp"
|
"src/mdebug.cpp"
|
||||||
"src/mem_utils.cpp"
|
"src/mem_utils.cpp"
|
||||||
@ -174,7 +174,6 @@ target_sources(metamod PRIVATE
|
|||||||
|
|
||||||
target_link_libraries(metamod PRIVATE
|
target_link_libraries(metamod PRIVATE
|
||||||
dl
|
dl
|
||||||
pthread
|
|
||||||
$<$<CONFIG:COMPAT_GLIBC>:libc-2.11.1.so>
|
$<$<CONFIG:COMPAT_GLIBC>:libc-2.11.1.so>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ COMPILER = g++
|
|||||||
|
|
||||||
OBJECTS = *.cpp
|
OBJECTS = *.cpp
|
||||||
|
|
||||||
LINK = -ldl
|
LINK =
|
||||||
|
|
||||||
OPT_FLAGS = -O3 -msse3 -flto -funroll-loops -fomit-frame-pointer -fno-stack-protector -fPIC
|
OPT_FLAGS = -O3 -msse3 -flto -funroll-loops -fomit-frame-pointer -fno-stack-protector -fPIC
|
||||||
|
|
||||||
@ -15,9 +15,9 @@ INCLUDE = -I. -I$(HLSDK)/common -I$(HLSDK)/dlls -I$(HLSDK)/engine \
|
|||||||
-I$(HLSDK)/game_shared -I$(HLSDK)/pm_shared -I$(HLSDK)/public -I$(METAMOD)
|
-I$(HLSDK)/game_shared -I$(HLSDK)/pm_shared -I$(HLSDK)/public -I$(METAMOD)
|
||||||
|
|
||||||
BIN_DIR = Release
|
BIN_DIR = Release
|
||||||
CFLAGS = $(OPT_FLAGS) -Wno-unused-result
|
CFLAGS = $(OPT_FLAGS)
|
||||||
|
|
||||||
CFLAGS += -g -DNDEBUG -Dlinux -D__linux__ -D__USE_GNU -std=gnu++11 -shared -m32
|
CFLAGS += -g -DNDEBUG -Dlinux -D__linux__ -D__USE_GNU -std=gnu++11 -shared
|
||||||
|
|
||||||
OBJ_LINUX := $(OBJECTS:%.c=$(BIN_DIR)/%.o)
|
OBJ_LINUX := $(OBJECTS:%.c=$(BIN_DIR)/%.o)
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ const RehldsFuncs_t* g_RehldsFuncs;
|
|||||||
IRehldsHookchains* g_RehldsHookchains;
|
IRehldsHookchains* g_RehldsHookchains;
|
||||||
IRehldsServerStatic* g_RehldsSvs;
|
IRehldsServerStatic* g_RehldsSvs;
|
||||||
|
|
||||||
bool rehlds_api_init(CSysModule* engineModule)
|
bool rehlds_api_try_init(CSysModule* engineModule, char* failureReason)
|
||||||
{
|
{
|
||||||
if (!engineModule) {
|
if (!engineModule) {
|
||||||
gpMetaUtilFuncs->pfnLogConsole(PLID, "Failed to locate engine module\n");
|
gpMetaUtilFuncs->pfnLogConsole(PLID, "Failed to locate engine module\n");
|
||||||
@ -16,13 +16,14 @@ bool rehlds_api_init(CSysModule* engineModule)
|
|||||||
|
|
||||||
CreateInterfaceFn ifaceFactory = Sys_GetFactory(engineModule);
|
CreateInterfaceFn ifaceFactory = Sys_GetFactory(engineModule);
|
||||||
if (!ifaceFactory) {
|
if (!ifaceFactory) {
|
||||||
gpMetaUtilFuncs->pfnLogConsole(PLID, "Failed to locate interface factory in engine module\n");
|
sprintf(failureReason, "Failed to locate interface factory in engine module\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int retCode = 0;
|
int retCode = 0;
|
||||||
g_RehldsApi = (IRehldsApi*)ifaceFactory(VREHLDS_HLDS_API_VERSION, &retCode);
|
g_RehldsApi = (IRehldsApi*)ifaceFactory(VREHLDS_HLDS_API_VERSION, &retCode);
|
||||||
if (!g_RehldsApi) {
|
if (!g_RehldsApi) {
|
||||||
|
sprintf(failureReason, "Failed to locate retrieve rehlds api interface from engine module, return code is %d\n", retCode);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,12 +31,12 @@ bool rehlds_api_init(CSysModule* engineModule)
|
|||||||
int minorVersion = g_RehldsApi->GetMinorVersion();
|
int minorVersion = g_RehldsApi->GetMinorVersion();
|
||||||
|
|
||||||
if (majorVersion != REHLDS_API_VERSION_MAJOR) {
|
if (majorVersion != REHLDS_API_VERSION_MAJOR) {
|
||||||
gpMetaUtilFuncs->pfnLogConsole(PLID, "REHLDS Api major version mismatch; expected %d, real %d\n", REHLDS_API_VERSION_MAJOR, majorVersion);
|
sprintf(failureReason, "REHLDS Api major version mismatch; expected %d, real %d\n", REHLDS_API_VERSION_MAJOR, majorVersion);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (minorVersion < REHLDS_API_VERSION_MINOR) {
|
if (minorVersion < REHLDS_API_VERSION_MINOR) {
|
||||||
gpMetaUtilFuncs->pfnLogConsole(PLID, "REHLDS Api minor version mismatch; expected at least %d, real %d\n", REHLDS_API_VERSION_MINOR, minorVersion);
|
sprintf(failureReason, "REHLDS Api minor version mismatch; expected at least %d, real %d\n", REHLDS_API_VERSION_MINOR, minorVersion);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,31 +47,25 @@ bool rehlds_api_init(CSysModule* engineModule)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool meta_init_rehlds_api()
|
bool meta_init_rehlds_api() {
|
||||||
{
|
char failReason[2048];
|
||||||
#ifdef _WIN32
|
|
||||||
// Find the most appropriate module handle from a list of DLL candidates
|
#ifdef WIN32
|
||||||
// Notes:
|
CSysModule* engineModule = Sys_LoadModule("swds.dll");
|
||||||
// - "swds.dll" is the library Dedicated Server
|
if (!rehlds_api_try_init(engineModule, failReason)) {
|
||||||
//
|
engineModule = Sys_LoadModule("filesystem_stdio.dll");
|
||||||
// Let's also attempt to locate the ReHLDS API in the client's library
|
if (!rehlds_api_try_init(engineModule, failReason)) {
|
||||||
// - "sw.dll" is the client library for Software render, with a built-in listenserver
|
gpMetaUtilFuncs->pfnLogConsole(PLID, "%s", failReason);
|
||||||
// - "hw.dll" is the client library for Hardware render, with a built-in listenserver
|
return false;
|
||||||
const char *dllNames[] = { "swds.dll", "hw.dll", "sw.dll" }; // List of DLL candidates to lookup for the ReHLDS API
|
}
|
||||||
CSysModule *engineModule = NULL; // The module handle of the selected DLL
|
|
||||||
for (const char *dllName : dllNames)
|
|
||||||
{
|
|
||||||
if (engineModule = Sys_GetModuleHandle(dllName))
|
|
||||||
break; // gotcha
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
CSysModule *engineModule = Sys_GetModuleHandle("engine_i486.so");
|
CSysModule* engineModule = Sys_LoadModule("engine_i486.so");
|
||||||
#endif
|
if (!rehlds_api_try_init(engineModule, failReason)) {
|
||||||
|
gpMetaUtilFuncs->pfnLogConsole(PLID, "%s", failReason);
|
||||||
if (!rehlds_api_init(engineModule)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -121,14 +121,6 @@ void *Sys_GetProcAddress(void *pModuleHandle, const char *pName)
|
|||||||
return GetProcAddress((HMODULE)pModuleHandle, pName);
|
return GetProcAddress((HMODULE)pModuleHandle, pName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Purpose: Returns a module handle by its name.
|
|
||||||
// Input : pModuleName - module name
|
|
||||||
// Output : the module handle or NULL in case of an error
|
|
||||||
CSysModule *Sys_GetModuleHandle(const char *pModuleName)
|
|
||||||
{
|
|
||||||
return reinterpret_cast<CSysModule *>(GetModuleHandle(pModuleName));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Purpose: Loads a DLL/component from disk and returns a handle to it
|
// Purpose: Loads a DLL/component from disk and returns a handle to it
|
||||||
// Input : *pModuleName - filename of the component
|
// Input : *pModuleName - filename of the component
|
||||||
// Output : opaque handle to the module (hides system dependency)
|
// Output : opaque handle to the module (hides system dependency)
|
||||||
|
@ -114,8 +114,6 @@ extern CreateInterfaceFn Sys_GetFactory(const char *pModuleName);
|
|||||||
// load/unload components
|
// load/unload components
|
||||||
class CSysModule;
|
class CSysModule;
|
||||||
|
|
||||||
extern CSysModule *Sys_GetModuleHandle(const char *pModuleName);
|
|
||||||
|
|
||||||
// Load & Unload should be called in exactly one place for each module
|
// Load & Unload should be called in exactly one place for each module
|
||||||
// The factory for that module should be passed on to dependent components for
|
// The factory for that module should be passed on to dependent components for
|
||||||
// proper versioning.
|
// proper versioning.
|
||||||
|
@ -1,173 +0,0 @@
|
|||||||
/*
|
|
||||||
physint.h - Server Physics Interface
|
|
||||||
Copyright (C) 2011 Uncle Mike
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef PHYSINT_H
|
|
||||||
#define PHYSINT_H
|
|
||||||
|
|
||||||
#include "eiface.h" // offsetof
|
|
||||||
|
|
||||||
#define SV_PHYSICS_INTERFACE_VERSION 6
|
|
||||||
|
|
||||||
#define STRUCT_FROM_LINK( l, t, m ) ((t *)((byte *)l - offsetof(t, m)))
|
|
||||||
#define EDICT_FROM_AREA( l ) STRUCT_FROM_LINK( l, edict_t, area )
|
|
||||||
|
|
||||||
// values that can be returned with pfnServerState
|
|
||||||
#define SERVER_DEAD 0
|
|
||||||
#define SERVER_LOADING 1
|
|
||||||
#define SERVER_ACTIVE 2
|
|
||||||
|
|
||||||
// LUMP reading errors
|
|
||||||
#define LUMP_LOAD_OK 0
|
|
||||||
#define LUMP_LOAD_COULDNT_OPEN 1
|
|
||||||
#define LUMP_LOAD_BAD_HEADER 2
|
|
||||||
#define LUMP_LOAD_BAD_VERSION 3
|
|
||||||
#define LUMP_LOAD_NO_EXTRADATA 4
|
|
||||||
#define LUMP_LOAD_INVALID_NUM 5
|
|
||||||
#define LUMP_LOAD_NOT_EXIST 6
|
|
||||||
#define LUMP_LOAD_MEM_FAILED 7
|
|
||||||
#define LUMP_LOAD_CORRUPTED 8
|
|
||||||
|
|
||||||
// LUMP saving errors
|
|
||||||
#define LUMP_SAVE_OK 0
|
|
||||||
#define LUMP_SAVE_COULDNT_OPEN 1
|
|
||||||
#define LUMP_SAVE_BAD_HEADER 2
|
|
||||||
#define LUMP_SAVE_BAD_VERSION 3
|
|
||||||
#define LUMP_SAVE_NO_EXTRADATA 4
|
|
||||||
#define LUMP_SAVE_INVALID_NUM 5
|
|
||||||
#define LUMP_SAVE_ALREADY_EXIST 6
|
|
||||||
#define LUMP_SAVE_NO_DATA 7
|
|
||||||
#define LUMP_SAVE_CORRUPTED 8
|
|
||||||
|
|
||||||
#ifndef ALLOC_CHECK
|
|
||||||
#define ALLOC_CHECK( x )
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct areanode_s
|
|
||||||
{
|
|
||||||
int axis; // -1 = leaf node
|
|
||||||
float dist;
|
|
||||||
struct areanode_s *children[2];
|
|
||||||
link_t trigger_edicts;
|
|
||||||
link_t solid_edicts;
|
|
||||||
link_t portal_edicts;
|
|
||||||
} areanode_t;
|
|
||||||
|
|
||||||
typedef struct server_physics_api_s
|
|
||||||
{
|
|
||||||
// unlink edict from old position and link onto new
|
|
||||||
void ( *pfnLinkEdict) ( edict_t *ent, qboolean touch_triggers );
|
|
||||||
double ( *pfnGetServerTime )( void ); // unclamped
|
|
||||||
double ( *pfnGetFrameTime )( void ); // unclamped
|
|
||||||
void* ( *pfnGetModel )( int modelindex );
|
|
||||||
areanode_t* ( *pfnGetHeadnode )( void ); // AABB tree for all physic entities
|
|
||||||
int ( *pfnServerState )( void );
|
|
||||||
void ( *pfnHost_Error )( const char *error, ... ); // cause Host Error
|
|
||||||
// ONLY ADD NEW FUNCTIONS TO THE END OF THIS STRUCT. INTERFACE VERSION IS FROZEN AT 6
|
|
||||||
struct triangleapi_s *pTriAPI; // draw coliisions etc. Only for local system
|
|
||||||
|
|
||||||
// draw debug messages (must be called from DrawOrthoTriangles). Only for local system
|
|
||||||
int ( *pfnDrawConsoleString )( int x, int y, char *string );
|
|
||||||
void ( *pfnDrawSetTextColor )( float r, float g, float b );
|
|
||||||
void ( *pfnDrawConsoleStringLen )( const char *string, int *length, int *height );
|
|
||||||
void ( *Con_NPrintf )( int pos, const char *fmt, ... );
|
|
||||||
void ( *Con_NXPrintf )( struct con_nprint_s *info, const char *fmt, ... );
|
|
||||||
const char *( *pfnGetLightStyle )( int style ); // read custom appreance for selected lightstyle
|
|
||||||
void ( *pfnUpdateFogSettings )( unsigned int packed_fog );
|
|
||||||
char **(*pfnGetFilesList)( const char *pattern, int *numFiles, int gamedironly );
|
|
||||||
struct msurface_s *(*pfnTraceSurface)( edict_t *pTextureEntity, const float *v1, const float *v2 );
|
|
||||||
const byte *(*pfnGetTextureData)( unsigned int texnum );
|
|
||||||
|
|
||||||
// static allocations
|
|
||||||
void *(*pfnMemAlloc)( size_t cb, const char *filename, const int fileline ) ALLOC_CHECK( 1 );
|
|
||||||
void (*pfnMemFree)( void *mem, const char *filename, const int fileline );
|
|
||||||
|
|
||||||
// trace & contents
|
|
||||||
int (*pfnMaskPointContents)( const float *pos, int groupmask );
|
|
||||||
trace_t (*pfnTrace)( const float *p0, float *mins, float *maxs, const float *p1, int type, edict_t *e );
|
|
||||||
trace_t (*pfnTraceNoEnts)( const float *p0, float *mins, float *maxs, const float *p1, int type, edict_t *e );
|
|
||||||
int (*pfnBoxInPVS)( const float *org, const float *boxmins, const float *boxmaxs );
|
|
||||||
|
|
||||||
// message handler (missed function to write raw bytes)
|
|
||||||
void (*pfnWriteBytes)( const byte *bytes, int count );
|
|
||||||
|
|
||||||
// BSP lump management
|
|
||||||
int (*pfnCheckLump)( const char *filename, const int lump, int *lumpsize );
|
|
||||||
int (*pfnReadLump)( const char *filename, const int lump, void **lumpdata, int *lumpsize );
|
|
||||||
int (*pfnSaveLump)( const char *filename, const int lump, void *lumpdata, int lumpsize );
|
|
||||||
|
|
||||||
// FS tools
|
|
||||||
int (*pfnSaveFile)( const char *filename, const void *data, int len );
|
|
||||||
const byte *(*pfnLoadImagePixels)( const char *filename, int *width, int *height );
|
|
||||||
|
|
||||||
const char *(*pfnGetModelName)( int modelindex );
|
|
||||||
|
|
||||||
// FWGS extension
|
|
||||||
void *(*pfnGetNativeObject)( const char *object );
|
|
||||||
} server_physics_api_t;
|
|
||||||
|
|
||||||
// physic callbacks
|
|
||||||
typedef struct physics_interface_s
|
|
||||||
{
|
|
||||||
int version;
|
|
||||||
// passed through pfnCreate (0 is attempt to create, -1 is reject)
|
|
||||||
int ( *SV_CreateEntity )( edict_t *pent, const char *szName );
|
|
||||||
// run custom physics for each entity (return 0 to use built-in engine physic)
|
|
||||||
int ( *SV_PhysicsEntity )( edict_t *pEntity );
|
|
||||||
// spawn entities with internal mod function e.g. for re-arrange spawn order (0 - use engine parser, 1 - use mod parser)
|
|
||||||
int ( *SV_LoadEntities )( const char *mapname, char *entities );
|
|
||||||
// update conveyor belt for clients
|
|
||||||
void ( *SV_UpdatePlayerBaseVelocity )( edict_t *ent );
|
|
||||||
// The game .dll should return 1 if save game should be allowed
|
|
||||||
int ( *SV_AllowSaveGame )( void );
|
|
||||||
// ONLY ADD NEW FUNCTIONS TO THE END OF THIS STRUCT. INTERFACE VERSION IS FROZEN AT 6
|
|
||||||
// override trigger area checking and touching
|
|
||||||
int ( *SV_TriggerTouch )( edict_t *pent, edict_t *trigger );
|
|
||||||
// some engine features can be enabled only through this function
|
|
||||||
unsigned int ( *SV_CheckFeatures )( void );
|
|
||||||
// used for draw debug collisions for custom physic engine etc
|
|
||||||
void ( *DrawDebugTriangles )( void );
|
|
||||||
// used for draw debug overlay (textured)
|
|
||||||
void ( *DrawNormalTriangles )( void );
|
|
||||||
// used for draw debug messages (2d mode)
|
|
||||||
void ( *DrawOrthoTriangles )( void );
|
|
||||||
// tracing entities with SOLID_CUSTOM mode on a server (not used by pmove code)
|
|
||||||
void ( *ClipMoveToEntity)( edict_t *ent, const float *start, float *mins, float *maxs, const float *end, trace_t *trace );
|
|
||||||
// tracing entities with SOLID_CUSTOM mode on a server (only used by pmove code)
|
|
||||||
void ( *ClipPMoveToEntity)( struct physent_s *pe, const float *start, float *mins, float *maxs, const float *end, struct pmtrace_s *tr );
|
|
||||||
// called at end the frame of SV_Physics call
|
|
||||||
void ( *SV_EndFrame )( void );
|
|
||||||
// obsolete
|
|
||||||
void (*pfnPrepWorldFrame)( void );
|
|
||||||
// called through save\restore process
|
|
||||||
void (*pfnCreateEntitiesInRestoreList)( SAVERESTOREDATA *pSaveData, int levelMask, qboolean create_world );
|
|
||||||
// allocate custom string (e.g. using user implementation of stringtable, not engine strings)
|
|
||||||
string_t (*pfnAllocString)( const char *szValue );
|
|
||||||
// make custom string (e.g. using user implementation of stringtable, not engine strings)
|
|
||||||
string_t (*pfnMakeString)( const char *szValue );
|
|
||||||
// read custom string (e.g. using user implementation of stringtable, not engine strings)
|
|
||||||
const char* (*pfnGetString)( string_t iString );
|
|
||||||
// helper for restore custom decals that have custom message (e.g. Paranoia)
|
|
||||||
int (*pfnRestoreDecal)( struct decallist_s *entry, edict_t *pEdict, qboolean adjacent );
|
|
||||||
// handle custom trigger touching for player
|
|
||||||
void (*PM_PlayerTouch)( struct playermove_s *ppmove, edict_t *client );
|
|
||||||
// alloc or destroy model custom data (called only for dedicated servers, otherwise using an client version)
|
|
||||||
void (*Mod_ProcessUserData)( struct model_s *mod, qboolean create, const byte *buffer );
|
|
||||||
// select BSP-hull for trace with specified mins\maxs
|
|
||||||
void *(*SV_HullForBsp)( edict_t *ent, const float *mins, const float *maxs, float *offset );
|
|
||||||
// handle player custom think function
|
|
||||||
int (*SV_PlayerThink)( edict_t *ent, float frametime, double time );
|
|
||||||
} physics_interface_t;
|
|
||||||
|
|
||||||
#endif//PHYSINT_H
|
|
@ -121,14 +121,6 @@ void *Sys_GetProcAddress(void *pModuleHandle, const char *pName)
|
|||||||
return GetProcAddress((HMODULE)pModuleHandle, pName);
|
return GetProcAddress((HMODULE)pModuleHandle, pName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Purpose: Returns a module handle by its name.
|
|
||||||
// Input : pModuleName - module name
|
|
||||||
// Output : the module handle or NULL in case of an error
|
|
||||||
CSysModule *Sys_GetModuleHandle(const char *pModuleName)
|
|
||||||
{
|
|
||||||
return reinterpret_cast<CSysModule *>(GetModuleHandle(pModuleName));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Purpose: Loads a DLL/component from disk and returns a handle to it
|
// Purpose: Loads a DLL/component from disk and returns a handle to it
|
||||||
// Input : *pModuleName - filename of the component
|
// Input : *pModuleName - filename of the component
|
||||||
// Output : opaque handle to the module (hides system dependency)
|
// Output : opaque handle to the module (hides system dependency)
|
||||||
|
@ -114,8 +114,6 @@ extern CreateInterfaceFn Sys_GetFactory(const char *pModuleName);
|
|||||||
// load/unload components
|
// load/unload components
|
||||||
class CSysModule;
|
class CSysModule;
|
||||||
|
|
||||||
extern CSysModule *Sys_GetModuleHandle(const char *pModuleName);
|
|
||||||
|
|
||||||
// Load & Unload should be called in exactly one place for each module
|
// Load & Unload should be called in exactly one place for each module
|
||||||
// The factory for that module should be passed on to dependent components for
|
// The factory for that module should be passed on to dependent components for
|
||||||
// proper versioning.
|
// proper versioning.
|
||||||
|
@ -151,6 +151,8 @@
|
|||||||
<ClCompile Include="..\src\engine_api.cpp" />
|
<ClCompile Include="..\src\engine_api.cpp" />
|
||||||
<ClCompile Include="..\src\game_support.cpp" />
|
<ClCompile Include="..\src\game_support.cpp" />
|
||||||
<ClCompile Include="..\src\h_export.cpp" />
|
<ClCompile Include="..\src\h_export.cpp" />
|
||||||
|
<ClCompile Include="..\src\linkent.cpp" />
|
||||||
|
<ClCompile Include="..\src\linkgame.cpp" />
|
||||||
<ClCompile Include="..\src\log_meta.cpp" />
|
<ClCompile Include="..\src\log_meta.cpp" />
|
||||||
<ClCompile Include="..\src\mdebug.cpp" />
|
<ClCompile Include="..\src\mdebug.cpp" />
|
||||||
<ClCompile Include="..\src\mem_utils.cpp" />
|
<ClCompile Include="..\src\mem_utils.cpp" />
|
||||||
@ -162,11 +164,6 @@
|
|||||||
<ClCompile Include="..\src\mplugin.cpp" />
|
<ClCompile Include="..\src\mplugin.cpp" />
|
||||||
<ClCompile Include="..\src\mreg.cpp" />
|
<ClCompile Include="..\src\mreg.cpp" />
|
||||||
<ClCompile Include="..\src\mutil.cpp" />
|
<ClCompile Include="..\src\mutil.cpp" />
|
||||||
<ClCompile Include="..\src\osdep_linkent_linux.cpp">
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\src\osdep_linkent_win32.cpp" />
|
|
||||||
<ClCompile Include="..\src\precompiled.cpp">
|
<ClCompile Include="..\src\precompiled.cpp">
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||||
|
@ -35,6 +35,12 @@
|
|||||||
<ClCompile Include="..\src\h_export.cpp">
|
<ClCompile Include="..\src\h_export.cpp">
|
||||||
<Filter>src</Filter>
|
<Filter>src</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\linkent.cpp">
|
||||||
|
<Filter>src</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\linkgame.cpp">
|
||||||
|
<Filter>src</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="..\src\log_meta.cpp">
|
<ClCompile Include="..\src\log_meta.cpp">
|
||||||
<Filter>src</Filter>
|
<Filter>src</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -92,12 +98,6 @@
|
|||||||
<ClCompile Include="..\src\meta_rehlds_api.cpp">
|
<ClCompile Include="..\src\meta_rehlds_api.cpp">
|
||||||
<Filter>src</Filter>
|
<Filter>src</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\src\osdep_linkent_win32.cpp">
|
|
||||||
<Filter>src</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\src\osdep_linkent_linux.cpp">
|
|
||||||
<Filter>src</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\src\api_info.h">
|
<ClInclude Include="..\src\api_info.h">
|
||||||
|
@ -12,12 +12,8 @@ NEW_DLL_FUNCTIONS sNewFunctionTable;
|
|||||||
NEW_DLL_FUNCTIONS sNewFunctionTable_jit;
|
NEW_DLL_FUNCTIONS sNewFunctionTable_jit;
|
||||||
NEW_DLL_FUNCTIONS *pHookedNewDllFunctions = &sNewFunctionTable;
|
NEW_DLL_FUNCTIONS *pHookedNewDllFunctions = &sNewFunctionTable;
|
||||||
|
|
||||||
// Unload game DLL and meta plugins
|
void MM_PRE_HOOK EXT_FUNC mm_GameShutdown()
|
||||||
void MM_POST_HOOK EXT_FUNC mm_GameShutdown()
|
|
||||||
{
|
{
|
||||||
g_metamod_active = false;
|
|
||||||
if (g_plugins && !g_dedicated_server) g_plugins->unload_all();
|
|
||||||
|
|
||||||
g_meta_extdll.unload();
|
g_meta_extdll.unload();
|
||||||
g_GameDLL.sys_module.unload();
|
g_GameDLL.sys_module.unload();
|
||||||
g_engine.sys_module.unload();
|
g_engine.sys_module.unload();
|
||||||
@ -134,7 +130,7 @@ compile_data_t g_dllfunc_cdata[] =
|
|||||||
compile_data_t g_newdllfunc_cdata[] =
|
compile_data_t g_newdllfunc_cdata[] =
|
||||||
{
|
{
|
||||||
CDATA_NEWDLL(pfnOnFreeEntPrivateData), // Called right before the object's memory is freed. Calls its destructor.
|
CDATA_NEWDLL(pfnOnFreeEntPrivateData), // Called right before the object's memory is freed. Calls its destructor.
|
||||||
CDATA_NEWDLL_H(pfnGameShutdown, P_POST, mm_GameShutdown), //
|
CDATA_NEWDLL_H(pfnGameShutdown, P_PRE, mm_GameShutdown), //
|
||||||
CDATA_NEWDLL(pfnShouldCollide), //
|
CDATA_NEWDLL(pfnShouldCollide), //
|
||||||
|
|
||||||
CDATA_NEWDLL(pfnCvarValue), // (fz) Use mm_CvarValue2 instead
|
CDATA_NEWDLL(pfnCvarValue), // (fz) Use mm_CvarValue2 instead
|
||||||
@ -221,33 +217,6 @@ C_DLLEXPORT int GetNewDLLFunctions(NEW_DLL_FUNCTIONS *pNewFunctionTable, int *in
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
C_DLLEXPORT int Server_GetPhysicsInterface(int iVersion, server_physics_api_t *pfuncsFromEngine, physics_interface_t *pFunctionTable)
|
|
||||||
{
|
|
||||||
// TODO: provide physint to plugins
|
|
||||||
if (iVersion != SV_PHYSICS_INTERFACE_VERSION || pfuncsFromEngine == nullptr || pFunctionTable == nullptr)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
|
|
||||||
// we have linkent alternative, shutdown linkent replacement
|
|
||||||
meta_shutdown_linkent_replacement();
|
|
||||||
|
|
||||||
// engine always require for nullptr, only replace single function needed for linkent alternative
|
|
||||||
Q_memset(pFunctionTable, 0, sizeof(*pFunctionTable));
|
|
||||||
pFunctionTable->SV_CreateEntity = [](edict_t *pent, const char *szName)
|
|
||||||
{
|
|
||||||
// check if gamedll implements this entity
|
|
||||||
ENTITY_FN SpawnEdict = reinterpret_cast<ENTITY_FN>(g_GameDLL.sys_module.getsym(szName));
|
|
||||||
|
|
||||||
// should we check metamod module itself? engine will do GPA on metamod module before failing back to this call anyway
|
|
||||||
if( !SpawnEdict )
|
|
||||||
return -1; // failed
|
|
||||||
|
|
||||||
SpawnEdict( &pent->v );
|
|
||||||
return 0; // handled
|
|
||||||
};
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void compile_dllfunc_callbacks()
|
void compile_dllfunc_callbacks()
|
||||||
{
|
{
|
||||||
jitdata_t jitdata;
|
jitdata_t jitdata;
|
||||||
|
@ -16,7 +16,6 @@ void WINAPI GiveFnptrsToDll(enginefuncs_t* pengfuncsFromEngine, globalvars_t* pG
|
|||||||
g_engine.funcs = &g_engfuncs;
|
g_engine.funcs = &g_engfuncs;
|
||||||
g_engine.globals = pGlobals;
|
g_engine.globals = pGlobals;
|
||||||
g_engfuncs = *pengfuncsFromEngine;
|
g_engfuncs = *pengfuncsFromEngine;
|
||||||
g_metamod_module.load(&g_engfuncs);
|
|
||||||
g_engine.sys_module.load(pengfuncsFromEngine);
|
g_engine.sys_module.load(pengfuncsFromEngine);
|
||||||
|
|
||||||
g_engfuncs = *pengfuncsFromEngine;
|
g_engfuncs = *pengfuncsFromEngine;
|
||||||
|
26
metamod/src/linkent.cpp
Normal file
26
metamod/src/linkent.cpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#include "precompiled.h"
|
||||||
|
|
||||||
|
// Function to perform common code of LINK_ENTITY_TO_GAME, rather than
|
||||||
|
// duplicating the code in ~2000 expanded macros. Based on code from Jussi
|
||||||
|
// Kivilinna <kijuhe00@students.oamk.fi>.
|
||||||
|
void NOINLINE do_link_ent(ENTITY_FN* pfnEntity, int* missing, const char* entStr, entvars_t* pev)
|
||||||
|
{
|
||||||
|
if (*missing) {
|
||||||
|
META_DEBUG(9, "Skipping entity '%s'; was previously found missing", entStr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!*pfnEntity) {
|
||||||
|
META_DEBUG(9, "Looking up game entity '%s'", entStr);
|
||||||
|
*pfnEntity = (ENTITY_FN)g_GameDLL.sys_module.getsym(entStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!*pfnEntity) {
|
||||||
|
META_ERROR("Couldn't find game entity '%s' in game DLL '%s': %s", entStr, g_GameDLL.name, CSysModule::getloaderror());
|
||||||
|
*missing = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
META_DEBUG(8, "Linking game entity '%s'", entStr);
|
||||||
|
(*pfnEntity)(pev);
|
||||||
|
}
|
@ -1,52 +1,19 @@
|
|||||||
// vi: set ts=4 sw=4 :
|
|
||||||
// vim: set tw=75 :
|
|
||||||
|
|
||||||
// linkent.h - export entities from mod "games" back to the HL engine
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
|
||||||
*
|
|
||||||
* This file is part of Metamod.
|
|
||||||
*
|
|
||||||
* Metamod is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Metamod is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Metamod; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Initializes replacement code
|
|
||||||
bool meta_init_linkent_replacement(CSysModule *moduleMetamod, CSysModule *moduleGame);
|
|
||||||
|
|
||||||
// Remove replacement code if new linkent mechanism was found
|
|
||||||
void meta_shutdown_linkent_replacement();
|
|
||||||
|
|
||||||
// Comments from SDK dlls/util.h:
|
// Comments from SDK dlls/util.h:
|
||||||
//! This is the glue that hooks .MAP entity class names to our CPP classes.
|
//! This is the glue that hooks .MAP entity class names to our CPP classes.
|
||||||
//! The _declspec forces them to be exported by name so we can do a lookup with GetProcAddress().
|
//! The _declspec forces them to be exported by name so we can do a lookup with GetProcAddress().
|
||||||
//! The function is used to intialize / allocate the object for the entity.
|
//! The function is used to intialize / allocate the object for the entity.
|
||||||
|
|
||||||
// Adapted from LINK_ENTITY_TO_FUNC in adminmod linkfunc.cpp.
|
// Adapted from LINK_ENTITY_TO_FUNC in adminmod linkfunc.cpp.
|
||||||
|
typedef void (*ENTITY_FN)(entvars_t *);
|
||||||
|
|
||||||
typedef void (*ENTITY_FN) (entvars_t *);
|
// Function to perform common code of LINK_ENTITY_TO_GAME.
|
||||||
|
void do_link_ent(ENTITY_FN* pfnEntity, int* missing, const char* entStr, entvars_t* pev);
|
||||||
|
|
||||||
|
#define LINK_ENTITY_TO_GAME(entityName) \
|
||||||
|
C_DLLEXPORT void entityName(entvars_t *pev) { \
|
||||||
|
static ENTITY_FN pfnEntity = nullptr; \
|
||||||
|
static int missing = 0; \
|
||||||
|
do_link_ent(&pfnEntity, &missing, STRINGIZE(entityName, 0), pev); \
|
||||||
|
}
|
||||||
|
9
metamod/src/linkgame.cpp
Normal file
9
metamod/src/linkgame.cpp
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#include "precompiled.h"
|
||||||
|
|
||||||
|
// Entity list for gamedlls adapted from adminmod linkfunc.cpp.
|
||||||
|
|
||||||
|
// NOTE: This list of entities is automatically generated via the script
|
||||||
|
// "mklinkgame.sh". See the files in the directory "ents" for the actual
|
||||||
|
// list of entities.
|
||||||
|
|
||||||
|
LINK_ENTITY_TO_GAME(worldspawn);
|
@ -46,26 +46,7 @@ bool rehlds_api_init(CSysModule* engineModule)
|
|||||||
|
|
||||||
bool meta_init_rehlds_api()
|
bool meta_init_rehlds_api()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
CSysModule* engineModule = Sys_LoadModule(ENGINE_LIB);
|
||||||
// Find the most appropriate module handle from a list of DLL candidates
|
|
||||||
// Notes:
|
|
||||||
// - "swds.dll" is the library Dedicated Server
|
|
||||||
//
|
|
||||||
// Let's also attempt to locate the ReHLDS API in the client's library
|
|
||||||
// - "sw.dll" is the client library for Software render, with a built-in listenserver
|
|
||||||
// - "hw.dll" is the client library for Hardware render, with a built-in listenserver
|
|
||||||
const char *dllNames[] = { "swds.dll", "hw.dll", "sw.dll" }; // List of DLL candidates to lookup for the ReHLDS API
|
|
||||||
CSysModule *engineModule = NULL; // The module handle of the selected DLL
|
|
||||||
for (const char *dllName : dllNames)
|
|
||||||
{
|
|
||||||
if (engineModule = Sys_GetModuleHandle(dllName))
|
|
||||||
break; // gotcha
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
CSysModule *engineModule = Sys_GetModuleHandle("engine_i486.so");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!rehlds_api_init(engineModule)) {
|
if (!rehlds_api_init(engineModule)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,6 @@ option_t g_global_options[] =
|
|||||||
|
|
||||||
gamedll_t g_GameDLL;
|
gamedll_t g_GameDLL;
|
||||||
|
|
||||||
CSysModule g_metamod_module;
|
|
||||||
|
|
||||||
ALIGN16
|
ALIGN16
|
||||||
meta_globals_t g_metaGlobals;
|
meta_globals_t g_metaGlobals;
|
||||||
|
|
||||||
@ -34,9 +32,6 @@ unsigned int g_CALL_API_count = 0;
|
|||||||
|
|
||||||
int g_requestid_counter = 0;
|
int g_requestid_counter = 0;
|
||||||
|
|
||||||
bool g_metamod_active = false;
|
|
||||||
bool g_dedicated_server = false;
|
|
||||||
|
|
||||||
// Very first metamod function that's run.
|
// Very first metamod function that's run.
|
||||||
// Do startup operations...
|
// Do startup operations...
|
||||||
void metamod_startup()
|
void metamod_startup()
|
||||||
@ -66,8 +61,6 @@ void metamod_startup()
|
|||||||
Sys_Error("Failure to init game DLL; exiting...");
|
Sys_Error("Failure to init game DLL; exiting...");
|
||||||
}
|
}
|
||||||
|
|
||||||
g_metamod_active = true;
|
|
||||||
|
|
||||||
// Register various console commands and cvars.
|
// Register various console commands and cvars.
|
||||||
// Can I do these here, rather than waiting for GameDLLInit() ?
|
// Can I do these here, rather than waiting for GameDLLInit() ?
|
||||||
// Looks like it works okay..
|
// Looks like it works okay..
|
||||||
@ -167,7 +160,6 @@ void metamod_startup()
|
|||||||
g_engine.pl_funcs.pfnCVarRegister = meta_CVarRegister;
|
g_engine.pl_funcs.pfnCVarRegister = meta_CVarRegister;
|
||||||
g_engine.pl_funcs.pfnCvar_RegisterVariable = meta_CVarRegister;
|
g_engine.pl_funcs.pfnCvar_RegisterVariable = meta_CVarRegister;
|
||||||
g_engine.pl_funcs.pfnRegUserMsg = meta_RegUserMsg;
|
g_engine.pl_funcs.pfnRegUserMsg = meta_RegUserMsg;
|
||||||
g_dedicated_server = g_engine.pl_funcs.pfnIsDedicatedServer() ? true : false;
|
|
||||||
|
|
||||||
if (g_engine.pl_funcs.pfnQueryClientCvarValue)
|
if (g_engine.pl_funcs.pfnQueryClientCvarValue)
|
||||||
g_engine.pl_funcs.pfnQueryClientCvarValue = meta_QueryClientCvarValue;
|
g_engine.pl_funcs.pfnQueryClientCvarValue = meta_QueryClientCvarValue;
|
||||||
@ -233,17 +225,10 @@ void metamod_startup()
|
|||||||
// Exit on failure here? Dunno...
|
// Exit on failure here? Dunno...
|
||||||
}
|
}
|
||||||
|
|
||||||
if (meta_init_rehlds_api()) {
|
meta_init_rehlds_api();
|
||||||
if (!g_meta_extdll.init(&g_engine.sys_module)) {
|
|
||||||
Sys_Error("Failure to init extension DLL; exiting...");
|
if (!g_meta_extdll.init(&g_engine.sys_module)) {
|
||||||
}
|
Sys_Error("Failure to init extension DLL; exiting...");
|
||||||
} else {
|
|
||||||
// activate linkent-replacement after give_engfuncs so that if game dll is
|
|
||||||
// plugin too and uses same method we get combined export table of plugin
|
|
||||||
// and game dll
|
|
||||||
if (!meta_init_linkent_replacement(&g_metamod_module, &g_GameDLL.sys_module)) {
|
|
||||||
Sys_Error("dll: Couldn't load linkent replacement for game DLL");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow for commands to metamod plugins at startup. Autoexec.cfg is
|
// Allow for commands to metamod plugins at startup. Autoexec.cfg is
|
||||||
@ -524,8 +509,6 @@ static void meta_apply_fix_data(std::vector<fixdata_t>& data)
|
|||||||
|
|
||||||
void meta_rebuild_callbacks()
|
void meta_rebuild_callbacks()
|
||||||
{
|
{
|
||||||
if (!g_metamod_active) return;
|
|
||||||
|
|
||||||
std::vector<fixdata_t> fixdata;
|
std::vector<fixdata_t> fixdata;
|
||||||
if (g_metaGlobals.esp_save) {
|
if (g_metaGlobals.esp_save) {
|
||||||
META_LOG("dll: Begin scan to collect callback fix data...");
|
META_LOG("dll: Begin scan to collect callback fix data...");
|
||||||
|
@ -15,9 +15,6 @@
|
|||||||
// cvar to contain version
|
// cvar to contain version
|
||||||
extern cvar_t g_meta_version;
|
extern cvar_t g_meta_version;
|
||||||
|
|
||||||
// metamod module handle
|
|
||||||
extern CSysModule g_metamod_module;
|
|
||||||
|
|
||||||
// Info about the game dll/mod.
|
// Info about the game dll/mod.
|
||||||
struct gamedll_t
|
struct gamedll_t
|
||||||
{
|
{
|
||||||
@ -77,9 +74,6 @@ extern unsigned int g_CALL_API_count;
|
|||||||
// stores previous requestid counter
|
// stores previous requestid counter
|
||||||
extern int g_requestid_counter;
|
extern int g_requestid_counter;
|
||||||
|
|
||||||
extern bool g_metamod_active;
|
|
||||||
extern bool g_dedicated_server;
|
|
||||||
|
|
||||||
// (patch by BAILOPAN)
|
// (patch by BAILOPAN)
|
||||||
// Holds cached player info, right now only things for querying cvars
|
// Holds cached player info, right now only things for querying cvars
|
||||||
// Max players is always 32, small enough that we can use a static array
|
// Max players is always 32, small enough that we can use a static array
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
CExtDll g_meta_extdll;
|
CExtDll g_meta_extdll;
|
||||||
|
|
||||||
CExtDll::CExtDll()
|
CExtDll::CExtDll()
|
||||||
: m_hGameDLL(CSysModule::INVALID_HANDLE)
|
: m_hGameDLL(CSysModule::INVALID_HANDLE), m_dlls(nullptr), m_count(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -17,6 +17,10 @@ void CExtDll::load()
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto extdll = &m_dlls[(*m_count)++];
|
||||||
|
Q_memset(extdll, 0, sizeof(*extdll));
|
||||||
|
extdll->lDLLHandle = m_hGameDLL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CExtDll::unload()
|
void CExtDll::unload()
|
||||||
@ -25,13 +29,68 @@ void CExtDll::unload()
|
|||||||
g_RehldsFuncs->RemoveExtDll(m_hGameDLL);
|
g_RehldsFuncs->RemoveExtDll(m_hGameDLL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto i = 0u; i < *m_count; i++)
|
||||||
|
{
|
||||||
|
if (m_dlls[i].lDLLHandle == m_hGameDLL)
|
||||||
|
{
|
||||||
|
--(*m_count);
|
||||||
|
if (*m_count != i)
|
||||||
|
{
|
||||||
|
Q_memmove(&m_dlls[i], &m_dlls[i + 1], (*m_count - i) * sizeof(m_dlls[0]));
|
||||||
|
i = *m_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_memset(&m_dlls[i], 0, sizeof(m_dlls[0]));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CExtDll::init(CSysModule *module)
|
bool CExtDll::init(CSysModule *module)
|
||||||
{
|
{
|
||||||
m_hGameDLL = g_GameDLL.sys_module.gethandle();
|
m_hGameDLL = g_GameDLL.sys_module.gethandle();
|
||||||
if (!m_hGameDLL)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
if (g_RehldsFuncs) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_dlls = (extensiondll_t *)module->getsym("g_rgextdll");
|
||||||
|
m_count = (size_t *)module->getsym("g_iextdllMac");
|
||||||
|
|
||||||
|
if (m_dlls && m_count) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// HACK HACK MORE HACK
|
||||||
|
// HLDS SHIT
|
||||||
|
auto pos = module->find_string_push("SV_SaveGameComment");
|
||||||
|
if (!pos) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char patterns[2][2][14] = {
|
||||||
|
{ "\x56\x33\xF6\x39\x2A\x2A\x2A\x2A\x2A\x7E\x2A\x53\x8B", "\x5B\xC3\x90\x90\xA1\x2A\x2A\x2A\x2A\x53\x56\x57\x33" },
|
||||||
|
{ "\x53\x8B\x2A\x2A\x2A\x2A\x2A\x57\xBF\x2A\x2A\x2A\x2A", "\x7E\x2A\x8B\x2A\x2A\x2A\x2A\x2A\xBE\x2A\x2A\x2A\x2A" },
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto i = 0u; i < ARRAYSIZE(patterns); i++)
|
||||||
|
{
|
||||||
|
auto addr = mem_find_pattern(pos - 33, 20, patterns[0][i], sizeof(patterns[0][i]) - 1);
|
||||||
|
if (!addr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_count = *(size_t **)(addr + 5);
|
||||||
|
|
||||||
|
addr = mem_find_pattern(addr, 30, patterns[1][i], sizeof(patterns[1][i]) - 1);
|
||||||
|
if (!addr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_dlls = *(extensiondll_t **)(addr + 9);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,8 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
module_handle_t m_hGameDLL;
|
module_handle_t m_hGameDLL;
|
||||||
|
extensiondll_t *m_dlls;
|
||||||
|
size_t *m_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern CExtDll g_meta_extdll;
|
extern CExtDll g_meta_extdll;
|
||||||
|
@ -573,15 +573,6 @@ void MPluginList::unpause_all()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unload all plugins currently loaded
|
|
||||||
void MPluginList::unload_all()
|
|
||||||
{
|
|
||||||
bool delayed;
|
|
||||||
for (auto p : m_plugins) {
|
|
||||||
p->unload(PT_ANYTIME, PNL_CMD_FORCED, delayed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retry any pending actions on plugins, for instance load/unload delayed
|
// Retry any pending actions on plugins, for instance load/unload delayed
|
||||||
// until changelevel.
|
// until changelevel.
|
||||||
void MPluginList::retry_all(PLUG_LOADTIME now)
|
void MPluginList::retry_all(PLUG_LOADTIME now)
|
||||||
|
@ -35,7 +35,6 @@ public:
|
|||||||
bool load(); // load the list, at startup
|
bool load(); // load the list, at startup
|
||||||
bool refresh(PLUG_LOADTIME now); // update from re-read inifile
|
bool refresh(PLUG_LOADTIME now); // update from re-read inifile
|
||||||
void unpause_all(); // unpause any paused plugins
|
void unpause_all(); // unpause any paused plugins
|
||||||
void unload_all(); // unload all plugins
|
|
||||||
void retry_all(PLUG_LOADTIME now); // retry any pending plugin actions
|
void retry_all(PLUG_LOADTIME now); // retry any pending plugin actions
|
||||||
void show(int source_index = 0); // list plugins to console use dynamic alignment
|
void show(int source_index = 0); // list plugins to console use dynamic alignment
|
||||||
void show_static(int source_index = 0); // list plugins to console use static alignment
|
void show_static(int source_index = 0); // list plugins to console use static alignment
|
||||||
|
@ -471,7 +471,7 @@ bool MPlugin::unload(PLUG_LOADTIME now, PL_UNLOAD_REASON reason, bool& delayed)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m_action != PA_UNLOAD && m_action != PA_RELOAD && reason != PNL_CMD_FORCED) {
|
if (m_action != PA_UNLOAD && m_action != PA_RELOAD) {
|
||||||
META_WARNING("dll: Not unloading plugin '%s'; not marked for unload (action=%s)", m_desc, str_action());
|
META_WARNING("dll: Not unloading plugin '%s'; not marked for unload (action=%s)", m_desc, str_action());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -64,21 +64,17 @@ MRegCmd* MRegCmdList::add(const char* addname, REG_CMD_FN cmd_handler, MPlugin*
|
|||||||
|
|
||||||
void MRegCmdList::remove(char* cmd_name)
|
void MRegCmdList::remove(char* cmd_name)
|
||||||
{
|
{
|
||||||
for (auto it = m_list.begin(); it != m_list.end(); ) {
|
for (auto it = m_list.begin(), end = m_list.end(); it != end; ++it) {
|
||||||
auto reg = *it;
|
auto reg = *it;
|
||||||
|
|
||||||
if (!Q_stricmp(reg->m_name, cmd_name)) {
|
if (!Q_stricmp(reg->m_name, cmd_name)) {
|
||||||
if (g_RehldsFuncs) {
|
if (g_RehldsFuncs) {
|
||||||
g_RehldsFuncs->Cmd_RemoveCmd(cmd_name);
|
g_RehldsFuncs->Cmd_RemoveCmd(cmd_name);
|
||||||
delete reg;
|
m_list.erase(it);
|
||||||
it = m_list.erase(it);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
reg->disable();
|
reg->disable();
|
||||||
it++;
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
it++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,22 +82,17 @@ void MRegCmdList::remove(char* cmd_name)
|
|||||||
// Disable any functions belonging to the given plugin (by index id).
|
// Disable any functions belonging to the given plugin (by index id).
|
||||||
void MRegCmdList::remove(int owner_plugin_id)
|
void MRegCmdList::remove(int owner_plugin_id)
|
||||||
{
|
{
|
||||||
for (auto it = m_list.begin(); it != m_list.end(); ) {
|
for (auto it = m_list.begin(), end = m_list.end(); it != end; ++it) {
|
||||||
auto reg = *it;
|
auto reg = *it;
|
||||||
|
|
||||||
if (reg->m_plugid != owner_plugin_id) {
|
if (reg->m_plugid == owner_plugin_id) {
|
||||||
it++;
|
if (g_RehldsFuncs) {
|
||||||
continue;
|
g_RehldsFuncs->Cmd_RemoveCmd(reg->m_name);
|
||||||
}
|
m_list.erase(it);
|
||||||
|
}
|
||||||
if (g_RehldsFuncs) {
|
else {
|
||||||
g_RehldsFuncs->Cmd_RemoveCmd(reg->m_name);
|
reg->disable();
|
||||||
delete reg;
|
}
|
||||||
it = m_list.erase(it);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
reg->disable();
|
|
||||||
it++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,233 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2004-2006 Jussi Kivilinna
|
|
||||||
*
|
|
||||||
* This file is part of "Metamod All-Mod-Support"-patch for Metamod.
|
|
||||||
*
|
|
||||||
* Metamod is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Metamod is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Metamod; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "precompiled.h"
|
|
||||||
|
|
||||||
#define PAGE_SIZE 4096UL
|
|
||||||
#define PAGE_MASK (~(PAGE_SIZE - 1))
|
|
||||||
#define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
|
|
||||||
|
|
||||||
//
|
|
||||||
// Linux code for dynamic linkents
|
|
||||||
// -- by Jussi Kivilinna
|
|
||||||
//
|
|
||||||
|
|
||||||
// opcode, e9, + sizeof pointer
|
|
||||||
#define BYTES_SIZE (1 + sizeof(void*))
|
|
||||||
|
|
||||||
typedef void *(*dlsym_func)(void *module, const char *funcname);
|
|
||||||
|
|
||||||
static void *gamedll_module_handle = 0;
|
|
||||||
static void *metamod_module_handle = 0;
|
|
||||||
|
|
||||||
// pointer to original dlsym
|
|
||||||
static dlsym_func dlsym_original;
|
|
||||||
|
|
||||||
// contains jmp to replacement_dlsym @dlsym_original
|
|
||||||
static unsigned char dlsym_new_bytes[BYTES_SIZE];
|
|
||||||
|
|
||||||
// contains original bytes of dlsym
|
|
||||||
static unsigned char dlsym_old_bytes[BYTES_SIZE];
|
|
||||||
|
|
||||||
// Mutex for our protection
|
|
||||||
static pthread_mutex_t mutex_replacement_dlsym = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
|
|
||||||
|
|
||||||
static int is_original_restored;
|
|
||||||
|
|
||||||
// constructs new jmp forwarder
|
|
||||||
inline void construct_jmp_instruction(void *x, void *place, void *target)
|
|
||||||
{
|
|
||||||
((unsigned char *)x)[0] = 0xe9;
|
|
||||||
*(unsigned long *)((char *)x + 1) = (unsigned long)target - ((unsigned long)place + 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
// checks if pointer x points to jump forwarder
|
|
||||||
inline bool is_code_trampoline_jmp_opcode(void *x)
|
|
||||||
{
|
|
||||||
return (((unsigned char *)x)[0] == 0xff || ((unsigned char *)x)[1] == 0x25);
|
|
||||||
}
|
|
||||||
|
|
||||||
// extracts pointer from "jmp dword ptr[pointer]"
|
|
||||||
inline void *extract_function_pointer_from_trampoline_jmp(void *x)
|
|
||||||
{
|
|
||||||
return (**(void ***)((char *)(x) + 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// restores old dlsym
|
|
||||||
//
|
|
||||||
inline void restore_original_dlsym()
|
|
||||||
{
|
|
||||||
//Copy old dlsym bytes back
|
|
||||||
memcpy((void *)dlsym_original, dlsym_old_bytes, BYTES_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// resets new dlsym
|
|
||||||
//
|
|
||||||
inline void reset_dlsym_hook()
|
|
||||||
{
|
|
||||||
//Copy new dlsym bytes back
|
|
||||||
memcpy((void *)dlsym_original, dlsym_new_bytes, BYTES_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Replacement dlsym function
|
|
||||||
//
|
|
||||||
static void *__replacement_dlsym(void *module, const char *funcname)
|
|
||||||
{
|
|
||||||
// these are needed in case dlsym calls dlsym, default one doesn't do
|
|
||||||
// it but some LD_PRELOADed library that hooks dlsym might actually
|
|
||||||
// do so.
|
|
||||||
int was_original_restored = is_original_restored;
|
|
||||||
|
|
||||||
// Lock before modifing original dlsym
|
|
||||||
pthread_mutex_lock(&mutex_replacement_dlsym);
|
|
||||||
|
|
||||||
// restore old dlsym
|
|
||||||
if (!is_original_restored)
|
|
||||||
{
|
|
||||||
restore_original_dlsym();
|
|
||||||
is_original_restored = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if we should hook this call
|
|
||||||
if (module != metamod_module_handle || !metamod_module_handle || !gamedll_module_handle)
|
|
||||||
{
|
|
||||||
//no metamod/gamedll module? should we remove hook now?
|
|
||||||
void *retval = dlsym_original(module, funcname);
|
|
||||||
if (metamod_module_handle && gamedll_module_handle)
|
|
||||||
{
|
|
||||||
if (!was_original_restored)
|
|
||||||
{
|
|
||||||
// reset dlsym hook
|
|
||||||
reset_dlsym_hook();
|
|
||||||
is_original_restored = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// no metamod/gamedll module? should we remove hook now by not reseting it back?
|
|
||||||
}
|
|
||||||
|
|
||||||
// unlock
|
|
||||||
pthread_mutex_unlock(&mutex_replacement_dlsym);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
// dlsym on metamod module
|
|
||||||
void *func = dlsym_original(module, funcname);
|
|
||||||
|
|
||||||
if (!func)
|
|
||||||
{
|
|
||||||
// function not in metamod module, try gamedll
|
|
||||||
func = dlsym_original(gamedll_module_handle, funcname);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!was_original_restored)
|
|
||||||
{
|
|
||||||
// reset dlsym hook
|
|
||||||
reset_dlsym_hook();
|
|
||||||
|
|
||||||
is_original_restored = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// unlock
|
|
||||||
pthread_mutex_unlock(&mutex_replacement_dlsym);
|
|
||||||
return func;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Initialize
|
|
||||||
//
|
|
||||||
bool meta_init_linkent_replacement(CSysModule *moduleMetamod, CSysModule *moduleGame)
|
|
||||||
{
|
|
||||||
metamod_module_handle = moduleMetamod->gethandle();
|
|
||||||
gamedll_module_handle = moduleGame->gethandle();
|
|
||||||
|
|
||||||
// dlsym is already known to be pointing to valid function, we loaded gamedll using it earlier!
|
|
||||||
void *sym_ptr = (void *)&dlsym;
|
|
||||||
while (is_code_trampoline_jmp_opcode(sym_ptr))
|
|
||||||
{
|
|
||||||
sym_ptr = extract_function_pointer_from_trampoline_jmp(sym_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
dlsym_original = (dlsym_func)sym_ptr;
|
|
||||||
|
|
||||||
// Backup old bytes of "dlsym" function
|
|
||||||
memcpy(dlsym_old_bytes, (void *)dlsym_original, BYTES_SIZE);
|
|
||||||
|
|
||||||
// Construct new bytes: "jmp offset[replacement_sendto] @ sendto_original"
|
|
||||||
construct_jmp_instruction((void *)&dlsym_new_bytes[0], (void *)dlsym_original, (void *)&__replacement_dlsym);
|
|
||||||
|
|
||||||
// Check if bytes overlap page border.
|
|
||||||
unsigned long start_of_page = PAGE_ALIGN((long)dlsym_original) - PAGE_SIZE;
|
|
||||||
unsigned long size_of_pages = 0;
|
|
||||||
|
|
||||||
if ((unsigned long)dlsym_original + BYTES_SIZE > PAGE_ALIGN((unsigned long)dlsym_original))
|
|
||||||
{
|
|
||||||
// bytes are located on two pages
|
|
||||||
size_of_pages = PAGE_SIZE * 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// bytes are located entirely on one page.
|
|
||||||
size_of_pages = PAGE_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove PROT_READ restriction
|
|
||||||
if (mprotect((void *)start_of_page, size_of_pages, PROT_READ | PROT_WRITE | PROT_EXEC))
|
|
||||||
{
|
|
||||||
META_ERROR("Couldn't initialize dynamic linkents, mprotect failed: %i. Exiting...", errno);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write our own jmp-forwarder on "dlsym"
|
|
||||||
reset_dlsym_hook();
|
|
||||||
|
|
||||||
// done
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void meta_shutdown_linkent_replacement()
|
|
||||||
{
|
|
||||||
// Lock before modifing original dlsym
|
|
||||||
pthread_mutex_lock(&mutex_replacement_dlsym);
|
|
||||||
|
|
||||||
// restore old dlsym
|
|
||||||
if (!is_original_restored)
|
|
||||||
{
|
|
||||||
restore_original_dlsym();
|
|
||||||
is_original_restored = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_unlock(&mutex_replacement_dlsym);
|
|
||||||
}
|
|
@ -1,251 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2004-2006 Jussi Kivilinna
|
|
||||||
*
|
|
||||||
* This file is part of "Metamod All-Mod-Support"-patch for Metamod.
|
|
||||||
*
|
|
||||||
* Metamod is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Metamod is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Metamod; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "precompiled.h"
|
|
||||||
|
|
||||||
//
|
|
||||||
// Win32 code for dynamic linkents
|
|
||||||
// -- by Jussi Kivilinna
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// Reads metamod.dll and game.dll function export tables and combines theim to
|
|
||||||
// single table that replaces metamod.dll's original table.
|
|
||||||
//
|
|
||||||
|
|
||||||
typedef struct sort_names_s {
|
|
||||||
unsigned long name;
|
|
||||||
unsigned short nameOrdinal;
|
|
||||||
} sort_names_t;
|
|
||||||
|
|
||||||
// relative virtual address to virtual address
|
|
||||||
#define rva_to_va(base, rva) ((unsigned long)base + (unsigned long)rva)
|
|
||||||
|
|
||||||
// virtual address to relative virtual address
|
|
||||||
#define va_to_rva(base, va) ((unsigned long)va - (unsigned long)base)
|
|
||||||
|
|
||||||
//
|
|
||||||
// Checks module signatures and return ntheaders pointer for valid module
|
|
||||||
//
|
|
||||||
static IMAGE_NT_HEADERS *get_ntheaders(HMODULE module)
|
|
||||||
{
|
|
||||||
union {
|
|
||||||
unsigned long mem;
|
|
||||||
IMAGE_DOS_HEADER * dos;
|
|
||||||
IMAGE_NT_HEADERS * pe;
|
|
||||||
} mem;
|
|
||||||
|
|
||||||
//Check if valid dos header
|
|
||||||
mem.mem = (unsigned long)module;
|
|
||||||
if (IsBadReadPtr(mem.dos, sizeof(*mem.dos)) || mem.dos->e_magic != IMAGE_DOS_SIGNATURE)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
//Get and check pe header
|
|
||||||
mem.mem = rva_to_va(module, mem.dos->e_lfanew);
|
|
||||||
if (IsBadReadPtr(mem.pe, sizeof(*mem.pe)) || mem.pe->Signature != IMAGE_NT_SIGNATURE)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return mem.pe;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Returns export table for valid module
|
|
||||||
//
|
|
||||||
static IMAGE_EXPORT_DIRECTORY *get_export_table(HMODULE module)
|
|
||||||
{
|
|
||||||
union {
|
|
||||||
unsigned long mem;
|
|
||||||
void * pvoid;
|
|
||||||
IMAGE_DOS_HEADER * dos;
|
|
||||||
IMAGE_NT_HEADERS * pe;
|
|
||||||
IMAGE_EXPORT_DIRECTORY * export_dir;
|
|
||||||
} mem;
|
|
||||||
|
|
||||||
// Check module
|
|
||||||
mem.pe = get_ntheaders(module);
|
|
||||||
if (!mem.pe)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
// Check for exports
|
|
||||||
if (!mem.pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
mem.mem = rva_to_va(module, mem.pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
|
|
||||||
if (IsBadReadPtr(mem.export_dir, sizeof(*mem.export_dir)))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return mem.export_dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Sort function for qsort
|
|
||||||
//
|
|
||||||
static int sort_names_list(const sort_names_t * A, const sort_names_t * B)
|
|
||||||
{
|
|
||||||
const char *str_A = (const char *)A->name;
|
|
||||||
const char *str_B = (const char *)B->name;
|
|
||||||
|
|
||||||
return Q_strcmp(str_A, str_B);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Combines meta_module and game_module export tables and replaces meta_module table with new one
|
|
||||||
//
|
|
||||||
static bool combine_module_export_tables(CSysModule *meta_module, CSysModule *game_module)
|
|
||||||
{
|
|
||||||
IMAGE_EXPORT_DIRECTORY * exportMM;
|
|
||||||
IMAGE_EXPORT_DIRECTORY * exportGame;
|
|
||||||
|
|
||||||
unsigned long newNumberOfFunctions;
|
|
||||||
unsigned long newNumberOfNames;
|
|
||||||
unsigned long * newFunctions;
|
|
||||||
unsigned long * newNames;
|
|
||||||
unsigned short * newNameOrdinals;
|
|
||||||
sort_names_t * newSort;
|
|
||||||
|
|
||||||
unsigned long i;
|
|
||||||
unsigned long u;
|
|
||||||
unsigned long funcCount;
|
|
||||||
unsigned long nameCount;
|
|
||||||
unsigned long listFix;
|
|
||||||
|
|
||||||
HMODULE moduleMeta = meta_module->gethandle();
|
|
||||||
HMODULE moduleGame = game_module->gethandle();
|
|
||||||
|
|
||||||
// Get export tables
|
|
||||||
exportMM = get_export_table(moduleMeta);
|
|
||||||
exportGame = get_export_table(moduleGame);
|
|
||||||
if (!exportMM || !exportGame)
|
|
||||||
{
|
|
||||||
META_ERROR("Couldn't initialize dynamic linkents, exportMM: %i, exportGame: %i. Exiting...", exportMM, exportGame);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// setup new export table
|
|
||||||
newNumberOfFunctions = exportMM->NumberOfFunctions + exportGame->NumberOfFunctions;
|
|
||||||
newNumberOfNames = exportMM->NumberOfNames + exportGame->NumberOfNames;
|
|
||||||
|
|
||||||
// alloc lists
|
|
||||||
*(void**)&newFunctions = calloc(1, newNumberOfFunctions * sizeof(*newFunctions));
|
|
||||||
*(void**)&newSort = calloc(1, newNumberOfNames * sizeof(*newSort));
|
|
||||||
|
|
||||||
// copy moduleMeta to new export
|
|
||||||
for (funcCount = 0; funcCount < exportMM->NumberOfFunctions; funcCount++)
|
|
||||||
newFunctions[funcCount] = rva_to_va(moduleMeta, ((unsigned long *)rva_to_va(moduleMeta, exportMM->AddressOfFunctions))[funcCount]);
|
|
||||||
|
|
||||||
for (nameCount = 0; nameCount < exportMM->NumberOfNames; nameCount++)
|
|
||||||
{
|
|
||||||
// fix name address
|
|
||||||
newSort[nameCount].name = rva_to_va(moduleMeta, ((unsigned long *)rva_to_va(moduleMeta, exportMM->AddressOfNames))[nameCount]);
|
|
||||||
|
|
||||||
// ordinal is index to function list
|
|
||||||
newSort[nameCount].nameOrdinal = ((unsigned short *)rva_to_va(moduleMeta, exportMM->AddressOfNameOrdinals))[nameCount];
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy moduleGame to new export
|
|
||||||
for (i = 0; i < exportGame->NumberOfFunctions; i++)
|
|
||||||
newFunctions[funcCount + i] = rva_to_va(moduleGame, ((unsigned long *)rva_to_va(moduleGame, exportGame->AddressOfFunctions))[i]);
|
|
||||||
|
|
||||||
for (i = 0, listFix = 0; i < exportGame->NumberOfNames; i++)
|
|
||||||
{
|
|
||||||
const char *name = (const char *)rva_to_va(moduleGame, ((unsigned long *)rva_to_va(moduleGame, exportGame->AddressOfNames))[i]);
|
|
||||||
//Check if name already in the list
|
|
||||||
for (u = 0; u < nameCount; u++)
|
|
||||||
{
|
|
||||||
if (!Q_stricmp(name, (const char *)newSort[u].name))
|
|
||||||
{
|
|
||||||
listFix -= 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (u < nameCount) //already in the list.. skip
|
|
||||||
continue;
|
|
||||||
|
|
||||||
newSort[nameCount + i + listFix].name = (unsigned long)name;
|
|
||||||
newSort[nameCount + i + listFix].nameOrdinal = (unsigned short)funcCount + ((unsigned short *)rva_to_va(moduleGame, exportGame->AddressOfNameOrdinals))[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
//set new number
|
|
||||||
newNumberOfNames = nameCount + i + listFix;
|
|
||||||
|
|
||||||
//sort names list
|
|
||||||
qsort(newSort, newNumberOfNames, sizeof(*newSort), (int(*)(const void*, const void*))&sort_names_list);
|
|
||||||
|
|
||||||
//make newNames and newNameOrdinals lists (VirtualAlloc so we dont waste heap memory to stuff that isn't freed)
|
|
||||||
*(void**)&newNames = VirtualAlloc(0, newNumberOfNames * sizeof(*newNames), MEM_COMMIT, PAGE_READWRITE);
|
|
||||||
*(void**)&newNameOrdinals = VirtualAlloc(0, newNumberOfNames * sizeof(*newNameOrdinals), MEM_COMMIT, PAGE_READWRITE);
|
|
||||||
|
|
||||||
for (i = 0; i < newNumberOfNames; i++)
|
|
||||||
{
|
|
||||||
newNames[i] = newSort[i].name;
|
|
||||||
newNameOrdinals[i] = newSort[i].nameOrdinal;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(newSort);
|
|
||||||
|
|
||||||
// translate VAs to RVAs
|
|
||||||
for (i = 0; i < newNumberOfFunctions; i++)
|
|
||||||
newFunctions[i] = va_to_rva(moduleMeta, newFunctions[i]);
|
|
||||||
|
|
||||||
for (i = 0; i < newNumberOfNames; i++)
|
|
||||||
{
|
|
||||||
newNames[i] = va_to_rva(moduleMeta, newNames[i]);
|
|
||||||
newNameOrdinals[i] = (unsigned short)va_to_rva(moduleMeta, newNameOrdinals[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD OldProtect;
|
|
||||||
if (!VirtualProtect(exportMM, sizeof(*exportMM), PAGE_READWRITE, &OldProtect))
|
|
||||||
{
|
|
||||||
META_ERROR("Couldn't initialize dynamic linkents, VirtualProtect failed: %i. Exiting...", GetLastError());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
exportMM->Base = 1;
|
|
||||||
exportMM->NumberOfFunctions = newNumberOfFunctions;
|
|
||||||
exportMM->NumberOfNames = newNumberOfNames;
|
|
||||||
*(unsigned long*)&(exportMM->AddressOfFunctions) = va_to_rva(moduleMeta, newFunctions);
|
|
||||||
*(unsigned long*)&(exportMM->AddressOfNames) = va_to_rva(moduleMeta, newNames);
|
|
||||||
*(unsigned long*)&(exportMM->AddressOfNameOrdinals) = va_to_rva(moduleMeta, newNameOrdinals);
|
|
||||||
|
|
||||||
VirtualProtect(exportMM, sizeof(*exportMM), OldProtect, &OldProtect);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool meta_init_linkent_replacement(CSysModule *moduleMetamod, CSysModule *moduleGame)
|
|
||||||
{
|
|
||||||
return combine_module_export_tables(moduleMetamod, moduleGame);
|
|
||||||
}
|
|
||||||
|
|
||||||
void meta_shutdown_linkent_replacement()
|
|
||||||
{
|
|
||||||
// no-op
|
|
||||||
}
|
|
@ -53,7 +53,6 @@
|
|||||||
#include "mem_utils.h"
|
#include "mem_utils.h"
|
||||||
#include "callback_jit.h"
|
#include "callback_jit.h"
|
||||||
#include "meta_rehlds_api.h"
|
#include "meta_rehlds_api.h"
|
||||||
#include "physint.h"
|
|
||||||
|
|
||||||
#undef CreateInterface
|
#undef CreateInterface
|
||||||
#include "linkent.h"
|
#include "linkent.h"
|
||||||
|
@ -68,7 +68,6 @@ module_handle_t CSysModule::load(const char *filepath)
|
|||||||
{
|
{
|
||||||
if (!m_handle) {
|
if (!m_handle) {
|
||||||
m_handle = LoadLibrary(filepath);
|
m_handle = LoadLibrary(filepath);
|
||||||
if (m_handle) m_free = true;
|
|
||||||
|
|
||||||
MODULEINFO module_info;
|
MODULEINFO module_info;
|
||||||
if (GetModuleInformation(GetCurrentProcess(), m_handle, &module_info, sizeof(module_info))) {
|
if (GetModuleInformation(GetCurrentProcess(), m_handle, &module_info, sizeof(module_info))) {
|
||||||
@ -158,7 +157,6 @@ module_handle_t CSysModule::load(const char *filepath)
|
|||||||
{
|
{
|
||||||
if (!m_handle) {
|
if (!m_handle) {
|
||||||
m_handle = dlopen(filepath, RTLD_NOW | RTLD_LOCAL | RTLD_DEEPBIND);
|
m_handle = dlopen(filepath, RTLD_NOW | RTLD_LOCAL | RTLD_DEEPBIND);
|
||||||
if (m_handle) m_free = true;
|
|
||||||
|
|
||||||
char buf[1024], dummy[1024], path[260];
|
char buf[1024], dummy[1024], path[260];
|
||||||
Q_sprintf(buf, "/proc/%i/maps", getpid());
|
Q_sprintf(buf, "/proc/%i/maps", getpid());
|
||||||
@ -194,7 +192,7 @@ bool CSysModule::unload()
|
|||||||
|
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
if (m_free) {
|
if (m_free) {
|
||||||
ret = dlclose(m_handle) == 0;
|
ret = dlclose(m_handle) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_handle = INVALID_HANDLE;
|
m_handle = INVALID_HANDLE;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user