mirror of
https://github.com/alliedmodders/sourcemod.git
synced 2025-12-16 02:57:19 +00:00
Compare commits
7 Commits
a65aef25ab
...
d4db62f199
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d4db62f199 | ||
|
|
c4d5235217 | ||
|
|
6439769d50 | ||
|
|
0c900be7fc | ||
|
|
1f39fc3265 | ||
|
|
600bbbcb54 | ||
|
|
21fce47352 |
221
.github/workflows/build-release.yml
vendored
Normal file
221
.github/workflows/build-release.yml
vendored
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
name: Build master branch
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
env:
|
||||||
|
ARCH: x86,x86_64
|
||||||
|
# Used for caching
|
||||||
|
# TODO: Handle this better so that we don't have to update this in lockstep with checkout-deps
|
||||||
|
MYSQL_VERSION: '5.5'
|
||||||
|
MMSOURCE_VERSION: '1.12'
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
permissions:
|
||||||
|
# For release creation, at the end
|
||||||
|
contents: write
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- platform: windows
|
||||||
|
os: windows-latest
|
||||||
|
os_short: win
|
||||||
|
- platform: linux
|
||||||
|
os: ubuntu-latest
|
||||||
|
os_short: linux
|
||||||
|
container_image: ghcr.io/alliedmodders/build-containers/debian11:latest
|
||||||
|
fail-fast: false
|
||||||
|
name: ${{ matrix.platform }}
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
container:
|
||||||
|
image: ${{ matrix.container_image }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout SourceMod
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
path: sourcemod
|
||||||
|
fetch-depth: 0
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Install Windows dependencies
|
||||||
|
if: startsWith(matrix.os, 'windows')
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
choco install -y gzip
|
||||||
|
choco install -y 7zip
|
||||||
|
|
||||||
|
# Add DIA SDK bin directory to PATH for dump_syms
|
||||||
|
Install-Module -Name VSSetup -Scope AllUsers -Force -AllowClobber
|
||||||
|
$vsRoot = Get-VSSetupInstance |
|
||||||
|
Sort-Object -Property InstallationVersion -Descending |
|
||||||
|
Select-Object -First 1 |
|
||||||
|
Select-Object -ExpandProperty InstallationPath
|
||||||
|
$diaDir = (Join-Path -Path $vsRoot -ChildPath 'DIA SDK\bin')
|
||||||
|
$diaDir | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||||
|
|
||||||
|
$toolsDir = New-Item -Path '_tools' -ItemType Directory -Force
|
||||||
|
$toolsDir.FullName | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||||
|
Push-Location $toolsDir
|
||||||
|
# TODO: Move this somewhere more official
|
||||||
|
curl -sSL -o dump_syms.exe https://users.alliedmods.net/~psychonic/dump_syms.exe
|
||||||
|
Unblock-File -Path dump_syms.exe
|
||||||
|
Pop-Location
|
||||||
|
|
||||||
|
# Largely a workaround for issue where github.workspace doesn't match $GITHUB_WORKSPACE
|
||||||
|
# in containerized jobs. See https://github.com/actions/runner/issues/2058
|
||||||
|
- name: Resolve paths
|
||||||
|
id: path_helper
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "dependencies=$GITHUB_WORKSPACE/dependencies" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Generate SDK list
|
||||||
|
id: sdk_list
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
sdk_list=()
|
||||||
|
for file in sourcemod/hl2sdk-manifests/manifests/*.json; do
|
||||||
|
sdk=$(basename "$file" .json)
|
||||||
|
if [[ $sdk == "mock" ]]; then
|
||||||
|
# We don't need to ship a build for the mock SDK
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
platform=$(jq -r '.platforms.${{ matrix.platform }}' "$file")
|
||||||
|
if [[ -z $platform || $platform == "null" || ${#platform[@]} -eq 0 ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
source2=$(jq -r '.source2' "$file")
|
||||||
|
if [[ $source2 == "null" || $source2 == "true" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
sdk_list+=("$sdk")
|
||||||
|
done
|
||||||
|
echo "sdk_list=$(printf '%s\n' "${sdk_list[@]}" | jq --raw-input . | jq --slurp --compact-output .)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Cache dependencies
|
||||||
|
uses: actions/cache@v4
|
||||||
|
env:
|
||||||
|
cache-name: hl2sdk-mysql-mmsource
|
||||||
|
with:
|
||||||
|
path: ${{ steps.path_helper.outputs.dependencies }}
|
||||||
|
key: ${{ runner.os }}-build-${{ env.cache-name }}-mysql${{ env.MYSQL_VERSION }}-mmsource${{ env.MMSOURCE_VERSION }}-${{ join(fromJson(steps.sdk_list.outputs.sdk_list), '') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-build-${{ env.cache-name }}-mysql${{ env.MYSQL_VERSION }}-mmsource${{ env.MMSOURCE_VERSION }}-
|
||||||
|
${{ runner.os }}-build-${{ env.cache-name }}-mysql${{ env.MYSQL_VERSION }}-
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
mkdir -p '${{ steps.path_helper.outputs.dependencies }}'
|
||||||
|
cd '${{ steps.path_helper.outputs.dependencies }}'
|
||||||
|
|
||||||
|
# Satisfy checkout-deps requirement for a "sourcemod" folder.
|
||||||
|
mkdir -p sourcemod
|
||||||
|
../sourcemod/tools/checkout-deps.sh -s ${{ join(fromJson(steps.sdk_list.outputs.sdk_list), ',') }}
|
||||||
|
|
||||||
|
if [ ! -f GeoLite2-City_20191217/GeoLite2-City.mmdb ]; then
|
||||||
|
geotar="GeoLite2-City_20191217.tar.gz"
|
||||||
|
curl -sSL "https://sm.alliedmods.net/$geotar" -o $geotar
|
||||||
|
tar -xzf "$geotar"
|
||||||
|
rm "$geotar"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
working-directory: sourcemod
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
BREAKPAD_SYMBOL_SERVER: ${{ vars.BREAKPAD_SYMBOL_SERVER }}
|
||||||
|
BREAKPAD_SYMBOL_SERVER_TOKEN: ${{ secrets.BREAKPAD_SYMBOL_SERVER_TOKEN }}
|
||||||
|
run: |
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
python3 ../configure.py \
|
||||||
|
--enable-optimize \
|
||||||
|
--breakpad-dump \
|
||||||
|
--no-color \
|
||||||
|
--symbol-files \
|
||||||
|
--sdks=${{ join(fromJson(steps.sdk_list.outputs.sdk_list), ',') }} \
|
||||||
|
--targets=${{ env.ARCH }} \
|
||||||
|
'--mms-path=${{ steps.path_helper.outputs.dependencies }}/mmsource-${{ env.MMSOURCE_VERSION }}' \
|
||||||
|
'--hl2sdk-root=${{ steps.path_helper.outputs.dependencies }}' \
|
||||||
|
'--mysql-path=${{ steps.path_helper.outputs.dependencies }}/mysql-${{ env.MYSQL_VERSION }}' \
|
||||||
|
'--mysql64-path=${{ steps.path_helper.outputs.dependencies }}/mysql-${{ env.MYSQL_VERSION }}-x86_64'
|
||||||
|
ambuild
|
||||||
|
|
||||||
|
mkdir -p addons/sourcemod/configs/geoip
|
||||||
|
cp '${{ steps.path_helper.outputs.dependencies }}/GeoLite2-City_20191217/GeoLite2-City.mmdb' addons/sourcemod/configs/geoip/GeoLite2-City.mmdb
|
||||||
|
|
||||||
|
- name: Package
|
||||||
|
id: package
|
||||||
|
working-directory: sourcemod/build/package
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
version_base=$(cat ../../product.version)
|
||||||
|
version_base=${version_base%-dev} # Ex. 1.12.0
|
||||||
|
version_rev=$(git rev-list --count HEAD)
|
||||||
|
version="${version_base}.${version_rev}"
|
||||||
|
expanded_version="${version_base}-git-${version_rev}"
|
||||||
|
|
||||||
|
if [ "${{ matrix.platform}}" == "windows" ]; then
|
||||||
|
filename="sourcemod-${expanded_version}-${{ matrix.platform }}.zip"
|
||||||
|
7z a "$filename" addons cfg
|
||||||
|
content_type="application/zip"
|
||||||
|
else
|
||||||
|
filename="sourcemod-${expanded_version}-${{ matrix.platform }}.tar.gz"
|
||||||
|
tar zcvf "$filename" addons cfg
|
||||||
|
content_type="application/gzip"
|
||||||
|
fi
|
||||||
|
echo "version=$version" >> $GITHUB_OUTPUT
|
||||||
|
echo "expanded_version=$expanded_version" >> $GITHUB_OUTPUT
|
||||||
|
echo "filename=$filename" >> $GITHUB_OUTPUT
|
||||||
|
echo "content_type=$content_type" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Create Release
|
||||||
|
id: create_release
|
||||||
|
uses: ncipollo/release-action@v1.14.0
|
||||||
|
with:
|
||||||
|
# Windows and Linux packages will need to upload to the same release
|
||||||
|
allowUpdates: true
|
||||||
|
replacesArtifacts: false
|
||||||
|
omitBodyDuringUpdate: true
|
||||||
|
omitDraftDuringUpdate: true
|
||||||
|
omitNameDuringUpdate: true
|
||||||
|
omitPrereleaseDuringUpdate: true
|
||||||
|
|
||||||
|
artifacts: sourcemod/build/package/${{ steps.package.outputs.filename }}
|
||||||
|
artifactContentType: ${{ steps.package.outputs.content_type }}
|
||||||
|
artifactErrorsFailBuild: true
|
||||||
|
|
||||||
|
tag: ${{ steps.package.outputs.version }}
|
||||||
|
commit: ${{ github.sha }}
|
||||||
|
generateReleaseNotes: true
|
||||||
|
|
||||||
|
draft: false
|
||||||
|
prerelease: ${{ github.ref == 'refs/heads/master' }}
|
||||||
|
makeLatest: ${{ github.ref != 'refs/heads/master' }}
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Output PDBs
|
||||||
|
if: startsWith(matrix.os, 'windows')
|
||||||
|
shell: pwsh
|
||||||
|
id: output_pdbs
|
||||||
|
working-directory: sourcemod/build
|
||||||
|
run: |
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
$paths = (Get-Content -Path "pdblog.txt" | ForEach-Object -Process {
|
||||||
|
$fullRelPath = Join-Path -Path 'sourcemod/build' -ChildPath $_
|
||||||
|
$fullRelPath -replace '\.pdb$', '.*'
|
||||||
|
}) -join "`n"
|
||||||
|
"PDB_PATHS<<EOF" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||||
|
$paths | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||||
|
"EOF" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||||
|
|
||||||
|
- name: Upload PDBs
|
||||||
|
if: startsWith(matrix.os, 'windows')
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: pdbs
|
||||||
|
path: ${{ env.PDB_PATHS }}
|
||||||
1
.github/workflows/ci.yml
vendored
1
.github/workflows/ci.yml
vendored
@ -2,7 +2,6 @@ name: Continuous Integration
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
|
||||||
- '[0-9]+.[0-9]+-dev'
|
- '[0-9]+.[0-9]+-dev'
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -12,3 +12,6 @@
|
|||||||
[submodule "public/safetyhook"]
|
[submodule "public/safetyhook"]
|
||||||
path = public/safetyhook
|
path = public/safetyhook
|
||||||
url = https://github.com/alliedmodders/safetyhook
|
url = https://github.com/alliedmodders/safetyhook
|
||||||
|
[submodule "core/logic/libaddrz"]
|
||||||
|
path = core/logic/libaddrz
|
||||||
|
url = https://github.com/dvander/libaddrz.git
|
||||||
|
|||||||
@ -16,7 +16,7 @@ CREATE TABLE IF NOT EXISTS sm_cookie_cache
|
|||||||
PRIMARY KEY (player, cookie_id)
|
PRIMARY KEY (player, cookie_id)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE LANGUAGE plpgsql;
|
CREATE OR REPLACE LANGUAGE plpgsql;
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION add_or_update_cookie(in_player VARCHAR(65), in_cookie INT, in_value VARCHAR(100), in_time INT) RETURNS VOID AS
|
CREATE OR REPLACE FUNCTION add_or_update_cookie(in_player VARCHAR(65), in_cookie INT, in_value VARCHAR(100), in_time INT) RETURNS VOID AS
|
||||||
$$
|
$$
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
CREATE TABLE sm_admins (
|
CREATE TABLE IF NOT EXISTS sm_admins (
|
||||||
id serial,
|
id serial,
|
||||||
authtype varchar(6) NOT NULL,
|
authtype varchar(6) NOT NULL,
|
||||||
CHECK (authtype in ('steam', 'name', 'ip')),
|
CHECK (authtype in ('steam', 'name', 'ip')),
|
||||||
@ -10,7 +10,7 @@ CREATE TABLE sm_admins (
|
|||||||
PRIMARY KEY (id)
|
PRIMARY KEY (id)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE sm_groups (
|
CREATE TABLE IF NOT EXISTS sm_groups (
|
||||||
id serial,
|
id serial,
|
||||||
flags varchar(30) NOT NULL,
|
flags varchar(30) NOT NULL,
|
||||||
name varchar(120) NOT NULL,
|
name varchar(120) NOT NULL,
|
||||||
@ -18,7 +18,7 @@ CREATE TABLE sm_groups (
|
|||||||
PRIMARY KEY (id)
|
PRIMARY KEY (id)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE sm_group_immunity (
|
CREATE TABLE IF NOT EXISTS sm_group_immunity (
|
||||||
group_id int NOT NULL,
|
group_id int NOT NULL,
|
||||||
other_id int NOT NULL,
|
other_id int NOT NULL,
|
||||||
FOREIGN KEY (group_id) REFERENCES sm_groups(id) ON DELETE CASCADE,
|
FOREIGN KEY (group_id) REFERENCES sm_groups(id) ON DELETE CASCADE,
|
||||||
@ -26,7 +26,7 @@ CREATE TABLE sm_group_immunity (
|
|||||||
PRIMARY KEY (group_id, other_id)
|
PRIMARY KEY (group_id, other_id)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE sm_group_overrides (
|
CREATE TABLE IF NOT EXISTS sm_group_overrides (
|
||||||
group_id int NOT NULL,
|
group_id int NOT NULL,
|
||||||
FOREIGN KEY (group_id) REFERENCES sm_groups(id) ON DELETE CASCADE,
|
FOREIGN KEY (group_id) REFERENCES sm_groups(id) ON DELETE CASCADE,
|
||||||
type varchar(10) NOT NULL,
|
type varchar(10) NOT NULL,
|
||||||
@ -37,7 +37,7 @@ CREATE TABLE sm_group_overrides (
|
|||||||
PRIMARY KEY (group_id, type, name)
|
PRIMARY KEY (group_id, type, name)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE sm_overrides (
|
CREATE TABLE IF NOT EXISTS sm_overrides (
|
||||||
type varchar(10) NOT NULL,
|
type varchar(10) NOT NULL,
|
||||||
CHECK (type in ('command', 'group')),
|
CHECK (type in ('command', 'group')),
|
||||||
name varchar(32) NOT NULL,
|
name varchar(32) NOT NULL,
|
||||||
@ -45,7 +45,7 @@ CREATE TABLE sm_overrides (
|
|||||||
PRIMARY KEY (type,name)
|
PRIMARY KEY (type,name)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE sm_admins_groups (
|
CREATE TABLE IF NOT EXISTS sm_admins_groups (
|
||||||
admin_id int NOT NULL,
|
admin_id int NOT NULL,
|
||||||
group_id int NOT NULL,
|
group_id int NOT NULL,
|
||||||
FOREIGN KEY (admin_id) REFERENCES sm_admins(id) ON DELETE CASCADE,
|
FOREIGN KEY (admin_id) REFERENCES sm_admins(id) ON DELETE CASCADE,
|
||||||
@ -56,10 +56,10 @@ CREATE TABLE sm_admins_groups (
|
|||||||
|
|
||||||
-- side note, this is pgsql module, sm_config will not exist if the above stuff exists... and it's being left to the admin
|
-- side note, this is pgsql module, sm_config will not exist if the above stuff exists... and it's being left to the admin
|
||||||
-- to figure out if it exists.
|
-- to figure out if it exists.
|
||||||
CREATE TABLE sm_config (
|
CREATE TABLE IF NOT EXISTS sm_config (
|
||||||
cfg_key varchar(32) NOT NULL,
|
cfg_key varchar(32) NOT NULL,
|
||||||
cfg_value varchar(255) NOT NULL,
|
cfg_value varchar(255) NOT NULL,
|
||||||
PRIMARY KEY (cfg_key)
|
PRIMARY KEY (cfg_key)
|
||||||
);
|
);
|
||||||
|
|
||||||
INSERT INTO sm_config (cfg_key, cfg_value) VALUES ('admin_version', '1.0.0.1409');
|
INSERT INTO sm_config (cfg_key, cfg_value) VALUES ('admin_version', '1.0.0.1409') ON CONFLICT (cfg_key) DO UPDATE SET cfg_value = EXCLUDED.cfg_value;
|
||||||
|
|||||||
@ -86,9 +86,15 @@ for cxx in builder.targets:
|
|||||||
'DatabaseConfBuilder.cpp',
|
'DatabaseConfBuilder.cpp',
|
||||||
'LumpManager.cpp',
|
'LumpManager.cpp',
|
||||||
'smn_entitylump.cpp',
|
'smn_entitylump.cpp',
|
||||||
|
'libaddrz/addrz.cpp',
|
||||||
|
'libaddrz/mapping.cpp',
|
||||||
|
'libaddrz/platform.cpp',
|
||||||
|
'libaddrz/proc_maps.cpp',
|
||||||
|
'PseudoAddrManager.cpp',
|
||||||
]
|
]
|
||||||
|
if binary.compiler.target.platform == 'linux':
|
||||||
if binary.compiler.target.arch == 'x86_64':
|
binary.sources += ['libaddrz/platform_linux.cpp']
|
||||||
binary.sources += ['PseudoAddrManager.cpp']
|
elif binary.compiler.target.platform == 'windows':
|
||||||
|
binary.sources += ['libaddrz/platform_windows.cpp']
|
||||||
|
|
||||||
SM.binaries += [builder.Add(binary)]
|
SM.binaries += [builder.Add(binary)]
|
||||||
|
|||||||
@ -330,6 +330,13 @@ bool CPlugin::ReadInfo()
|
|||||||
else
|
else
|
||||||
m_MaxClientsVar = nullptr;
|
m_MaxClientsVar = nullptr;
|
||||||
|
|
||||||
|
if (base->FindPubvarByName("PointerSize", &idx) == SP_ERROR_NONE) {
|
||||||
|
sp_pubvar_t* var = nullptr;
|
||||||
|
if (base->GetPubvarByIndex(idx, &var) == SP_ERROR_NONE && var) {
|
||||||
|
*var->offs = sizeof(void*);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "PseudoAddrManager.h"
|
#include "PseudoAddrManager.h"
|
||||||
|
#include <bridge/include/CoreProvider.h>
|
||||||
#ifdef PLATFORM_APPLE
|
#ifdef PLATFORM_APPLE
|
||||||
#include <mach/mach.h>
|
#include <mach/mach.h>
|
||||||
#include <mach/vm_region.h>
|
#include <mach/vm_region.h>
|
||||||
@ -35,135 +36,88 @@
|
|||||||
#ifdef PLATFORM_LINUX
|
#ifdef PLATFORM_LINUX
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef PLATFORM_WINDOWS
|
||||||
|
#include <Psapi.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
PseudoAddressManager::PseudoAddressManager() : m_NumEntries(0)
|
PseudoAddressManager::PseudoAddressManager() : m_dictionary(am::IPlatform::GetDefault())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// A pseudo address consists of a table index in the upper 6 bits and an offset in the
|
void PseudoAddressManager::Initialize() {
|
||||||
// lower 26 bits. The table consists of memory allocation base addresses.
|
#ifdef PLATFORM_WINDOWS
|
||||||
|
auto process = GetCurrentProcess();
|
||||||
|
auto get_module_details = [process](const char* name, void*& baseAddress, size_t& moduleSize) {
|
||||||
|
if (process == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto hndl = GetModuleHandle(name);
|
||||||
|
if (hndl == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
MODULEINFO info;
|
||||||
|
if (!GetModuleInformation(process, hndl, &info, sizeof(info))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
moduleSize = info.SizeOfImage;
|
||||||
|
baseAddress = info.lpBaseOfDll;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
#ifdef PLATFORM_LINUX
|
||||||
|
auto get_module_details = [](const char* name, void* baseAddress, size_t& moduleSize) {
|
||||||
|
auto hndl = dlopen(name, RTLD_NOLOAD);
|
||||||
|
if (hndl == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
void* addr = dlsym(hndl, "CreateInterface");
|
||||||
|
dlclose(hndl);
|
||||||
|
|
||||||
|
if (!addr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dl_info info;
|
||||||
|
if (dladdr(addr, &info) == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
baseAddress = info.dli_fbase;
|
||||||
|
// It doesn't matter much if we figure out the module size
|
||||||
|
// libaddrz coalesce maps on linux
|
||||||
|
moduleSize = 0;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Early map commonly used modules, it's okay if not all of them are here
|
||||||
|
// Everything else will be caught by "ToPseudoAddress" but you risk running out of ranges by then
|
||||||
|
const char* libs[] = { "engine", "server", "tier0", "vstdlib" };
|
||||||
|
|
||||||
|
char formattedName[64];
|
||||||
|
for (int i = 0; i < sizeof(libs) / sizeof(const char*); i++) {
|
||||||
|
bridge->FormatSourceBinaryName(libs[i], formattedName, sizeof(formattedName));
|
||||||
|
void* base_addr = nullptr;
|
||||||
|
size_t module_size = 0;
|
||||||
|
if (get_module_details(formattedName, base_addr, module_size)) {
|
||||||
|
// Create the mapping (hopefully)
|
||||||
|
m_dictionary.Make32bitAddress(base_addr, module_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void *PseudoAddressManager::FromPseudoAddress(uint32_t paddr)
|
void *PseudoAddressManager::FromPseudoAddress(uint32_t paddr)
|
||||||
{
|
{
|
||||||
#ifdef KE_ARCH_X64
|
if (paddr == 0) {
|
||||||
uint8_t index = paddr >> PSEUDO_OFFSET_BITS;
|
|
||||||
uint32_t offset = paddr & ((1 << PSEUDO_OFFSET_BITS) - 1);
|
|
||||||
|
|
||||||
if (index >= m_NumEntries)
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
}
|
||||||
return reinterpret_cast<void *>(uintptr_t(m_AllocBases[index]) + offset);
|
return m_dictionary.RecoverAddress(paddr).value_or(nullptr);
|
||||||
#else
|
|
||||||
return nullptr;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t PseudoAddressManager::ToPseudoAddress(void *addr)
|
uint32_t PseudoAddressManager::ToPseudoAddress(void *addr)
|
||||||
{
|
{
|
||||||
#ifdef KE_ARCH_X64
|
if (addr == nullptr) {
|
||||||
uint8_t index = 0;
|
|
||||||
uint32_t offset = 0;
|
|
||||||
bool hasEntry = false;
|
|
||||||
void *base = GetAllocationBase(addr);
|
|
||||||
|
|
||||||
if (base) {
|
|
||||||
for (int i = 0; i < m_NumEntries; i++) {
|
|
||||||
if (m_AllocBases[i] == base) {
|
|
||||||
index = i;
|
|
||||||
hasEntry = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
return m_dictionary.Make32bitAddress(addr).value_or(0);
|
||||||
if (!hasEntry) {
|
|
||||||
index = m_NumEntries;
|
|
||||||
if (m_NumEntries < SM_ARRAYSIZE(m_AllocBases))
|
|
||||||
m_AllocBases[m_NumEntries++] = base;
|
|
||||||
else
|
|
||||||
return 0; // Table is full
|
|
||||||
}
|
|
||||||
|
|
||||||
ptrdiff_t diff = uintptr_t(addr) - uintptr_t(base);
|
|
||||||
|
|
||||||
// Ensure difference fits in 26 bits
|
|
||||||
if (diff > (UINT32_MAX >> PSEUDO_INDEX_BITS))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return (index << PSEUDO_OFFSET_BITS) | diff;
|
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void *PseudoAddressManager::GetAllocationBase(void *ptr)
|
|
||||||
{
|
|
||||||
#if defined PLATFORM_WINDOWS
|
|
||||||
|
|
||||||
MEMORY_BASIC_INFORMATION info;
|
|
||||||
if (!VirtualQuery(ptr, &info, sizeof(MEMORY_BASIC_INFORMATION)))
|
|
||||||
return nullptr;
|
|
||||||
return info.AllocationBase;
|
|
||||||
|
|
||||||
#elif defined PLATFORM_APPLE
|
|
||||||
|
|
||||||
#ifdef KE_ARCH_X86
|
|
||||||
typedef vm_region_info_t mach_vm_region_info_t;
|
|
||||||
typedef vm_region_basic_info_data_t mach_vm_region_basic_info_data_t;
|
|
||||||
const vm_region_flavor_t MACH_VM_REGION_BASIC_INFO = VM_REGION_BASIC_INFO;
|
|
||||||
const mach_msg_type_number_t MACH_VM_REGION_BASIC_INFO_COUNT = VM_REGION_BASIC_INFO_COUNT;
|
|
||||||
#define mach_vm_region vm_region
|
|
||||||
#elif defined KE_ARCH_X64
|
|
||||||
typedef vm_region_info_64_t mach_vm_region_info_t ;
|
|
||||||
typedef vm_region_basic_info_data_64_t mach_vm_region_basic_info_data_t;
|
|
||||||
const vm_region_flavor_t MACH_VM_REGION_BASIC_INFO = VM_REGION_BASIC_INFO_64;
|
|
||||||
const mach_msg_type_number_t MACH_VM_REGION_BASIC_INFO_COUNT = VM_REGION_BASIC_INFO_COUNT_64;
|
|
||||||
#define mach_vm_region vm_region_64
|
|
||||||
#endif
|
|
||||||
vm_size_t size;
|
|
||||||
vm_address_t vmaddr = reinterpret_cast<vm_address_t>(ptr);
|
|
||||||
mach_vm_region_basic_info_data_t info;
|
|
||||||
memory_object_name_t obj;
|
|
||||||
vm_region_flavor_t flavor = MACH_VM_REGION_BASIC_INFO;
|
|
||||||
mach_msg_type_number_t count = MACH_VM_REGION_BASIC_INFO_COUNT;
|
|
||||||
|
|
||||||
kern_return_t kr = mach_vm_region(mach_task_self(), &vmaddr, &size, flavor,
|
|
||||||
reinterpret_cast<mach_vm_region_info_t>(&info),
|
|
||||||
&count, &obj);
|
|
||||||
|
|
||||||
if (kr != KERN_SUCCESS)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return reinterpret_cast<void *>(vmaddr);
|
|
||||||
|
|
||||||
#elif defined PLATFORM_LINUX
|
|
||||||
|
|
||||||
uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
|
|
||||||
|
|
||||||
// Format:
|
|
||||||
// lower upper prot stuff path
|
|
||||||
// 08048000-0804c000 r-xp 00000000 03:03 1010107 /bin/cat
|
|
||||||
FILE *fp = fopen("/proc/self/maps", "r");
|
|
||||||
if (fp) {
|
|
||||||
uintptr_t lower, upper;
|
|
||||||
while (fscanf(fp, "%" PRIxPTR "-%" PRIxPTR, &lower, &upper) != EOF) {
|
|
||||||
if (addr >= lower && addr <= upper) {
|
|
||||||
fclose(fp);
|
|
||||||
return reinterpret_cast<void *>(lower);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read to end of line
|
|
||||||
int c;
|
|
||||||
while ((c = fgetc(fp)) != '\n') {
|
|
||||||
if (c == EOF)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (c == EOF)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,6 +31,7 @@
|
|||||||
#define _INCLUDE_SOURCEMOD_PSEUDOADDRESSMANAGER_H_
|
#define _INCLUDE_SOURCEMOD_PSEUDOADDRESSMANAGER_H_
|
||||||
|
|
||||||
#include "common_logic.h"
|
#include "common_logic.h"
|
||||||
|
#include "libaddrz/addrz.h"
|
||||||
|
|
||||||
class PseudoAddressManager
|
class PseudoAddressManager
|
||||||
{
|
{
|
||||||
@ -39,13 +40,9 @@ public:
|
|||||||
public:
|
public:
|
||||||
void *FromPseudoAddress(uint32_t paddr);
|
void *FromPseudoAddress(uint32_t paddr);
|
||||||
uint32_t ToPseudoAddress(void *addr);
|
uint32_t ToPseudoAddress(void *addr);
|
||||||
|
void Initialize();
|
||||||
private:
|
private:
|
||||||
void *GetAllocationBase(void *ptr);
|
am::AddressDict m_dictionary;
|
||||||
private:
|
|
||||||
static constexpr uint8_t PSEUDO_OFFSET_BITS = 26;
|
|
||||||
static constexpr uint8_t PSEUDO_INDEX_BITS = sizeof(uint32_t) * 8 - PSEUDO_OFFSET_BITS;
|
|
||||||
void *m_AllocBases[1 << PSEUDO_INDEX_BITS];
|
|
||||||
uint8_t m_NumEntries;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _INCLUDE_SOURCEMOD_PSEUDOADDRESSMANAGER_H_
|
#endif // _INCLUDE_SOURCEMOD_PSEUDOADDRESSMANAGER_H_
|
||||||
|
|||||||
@ -57,6 +57,7 @@
|
|||||||
#include "RootConsoleMenu.h"
|
#include "RootConsoleMenu.h"
|
||||||
#include "CellArray.h"
|
#include "CellArray.h"
|
||||||
#include "smn_entitylump.h"
|
#include "smn_entitylump.h"
|
||||||
|
#include "PseudoAddrManager.h"
|
||||||
#include <bridge/include/BridgeAPI.h>
|
#include <bridge/include/BridgeAPI.h>
|
||||||
#include <bridge/include/IProviderCallbacks.h>
|
#include <bridge/include/IProviderCallbacks.h>
|
||||||
|
|
||||||
@ -86,9 +87,7 @@ IScriptManager *scripts = &g_PluginSys;
|
|||||||
IExtensionSys *extsys = &g_Extensions;
|
IExtensionSys *extsys = &g_Extensions;
|
||||||
ILogger *logger = &g_Logger;
|
ILogger *logger = &g_Logger;
|
||||||
CNativeOwner g_CoreNatives;
|
CNativeOwner g_CoreNatives;
|
||||||
#ifdef KE_ARCH_X64
|
|
||||||
PseudoAddressManager pseudoAddr;
|
PseudoAddressManager pseudoAddr;
|
||||||
#endif
|
|
||||||
|
|
||||||
EntityLumpParseResult lastParseResult;
|
EntityLumpParseResult lastParseResult;
|
||||||
|
|
||||||
@ -122,20 +121,12 @@ static void RegisterProfiler(IProfilingTool *tool)
|
|||||||
|
|
||||||
static void *FromPseudoAddress(uint32_t paddr)
|
static void *FromPseudoAddress(uint32_t paddr)
|
||||||
{
|
{
|
||||||
#ifdef KE_ARCH_X64
|
|
||||||
return pseudoAddr.FromPseudoAddress(paddr);
|
return pseudoAddr.FromPseudoAddress(paddr);
|
||||||
#else
|
|
||||||
return nullptr;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t ToPseudoAddress(void *addr)
|
static uint32_t ToPseudoAddress(void *addr)
|
||||||
{
|
{
|
||||||
#ifdef KE_ARCH_X64
|
|
||||||
return pseudoAddr.ToPseudoAddress(addr);
|
return pseudoAddr.ToPseudoAddress(addr);
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetEntityLumpWritable(bool writable)
|
static void SetEntityLumpWritable(bool writable)
|
||||||
@ -236,6 +227,7 @@ static void logic_init(CoreProvider* core, sm_logic_t* _logic)
|
|||||||
g_pSourcePawn2 = *core->spe2;
|
g_pSourcePawn2 = *core->spe2;
|
||||||
SMGlobalClass::head = core->listeners;
|
SMGlobalClass::head = core->listeners;
|
||||||
|
|
||||||
|
pseudoAddr.Initialize();
|
||||||
g_ShareSys.Initialize();
|
g_ShareSys.Initialize();
|
||||||
g_pCoreIdent = g_ShareSys.CreateCoreIdentity();
|
g_pCoreIdent = g_ShareSys.CreateCoreIdentity();
|
||||||
|
|
||||||
|
|||||||
1
core/logic/libaddrz
Submodule
1
core/logic/libaddrz
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 661cd316e6ff8e8560efa20db1794f3fa479647c
|
||||||
@ -59,6 +59,7 @@
|
|||||||
#include <bridge/include/CoreProvider.h>
|
#include <bridge/include/CoreProvider.h>
|
||||||
#include <bridge/include/IScriptManager.h>
|
#include <bridge/include/IScriptManager.h>
|
||||||
#include <bridge/include/IExtensionBridge.h>
|
#include <bridge/include/IExtensionBridge.h>
|
||||||
|
#include "PseudoAddrManager.h"
|
||||||
#include <sh_vector.h>
|
#include <sh_vector.h>
|
||||||
|
|
||||||
using namespace SourceMod;
|
using namespace SourceMod;
|
||||||
@ -863,11 +864,10 @@ enum NumberType
|
|||||||
|
|
||||||
static cell_t LoadFromAddress(IPluginContext *pContext, const cell_t *params)
|
static cell_t LoadFromAddress(IPluginContext *pContext, const cell_t *params)
|
||||||
{
|
{
|
||||||
#ifdef KE_ARCH_X86
|
|
||||||
void *addr = reinterpret_cast<void*>(params[1]);
|
void *addr = reinterpret_cast<void*>(params[1]);
|
||||||
#else
|
if (pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
|
||||||
void *addr = pseudoAddr.FromPseudoAddress(params[1]);
|
addr = pseudoAddr.FromPseudoAddress(params[1]);
|
||||||
#endif
|
}
|
||||||
|
|
||||||
if (addr == NULL)
|
if (addr == NULL)
|
||||||
{
|
{
|
||||||
@ -892,14 +892,12 @@ static cell_t LoadFromAddress(IPluginContext *pContext, const cell_t *params)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static cell_t StoreToAddress(IPluginContext *pContext, const cell_t *params)
|
static cell_t StoreToAddress(IPluginContext *pContext, const cell_t *params)
|
||||||
{
|
{
|
||||||
#ifdef KE_ARCH_X86
|
|
||||||
void *addr = reinterpret_cast<void*>(params[1]);
|
void *addr = reinterpret_cast<void*>(params[1]);
|
||||||
#else
|
if (pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
|
||||||
void *addr = pseudoAddr.FromPseudoAddress(params[1]);
|
addr = pseudoAddr.FromPseudoAddress(params[1]);
|
||||||
#endif
|
}
|
||||||
|
|
||||||
if (addr == NULL)
|
if (addr == NULL)
|
||||||
{
|
{
|
||||||
@ -950,6 +948,60 @@ static cell_t StoreToAddress(IPluginContext *pContext, const cell_t *params)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static cell_t LoadAddressFromAddress(IPluginContext *pContext, const cell_t *params)
|
||||||
|
{
|
||||||
|
void *addr = reinterpret_cast<void*>(params[1]);
|
||||||
|
if (pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
|
||||||
|
addr = pseudoAddr.FromPseudoAddress(params[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addr == NULL)
|
||||||
|
{
|
||||||
|
return pContext->ThrowNativeError("Address cannot be null");
|
||||||
|
}
|
||||||
|
else if (reinterpret_cast<uintptr_t>(addr) < VALID_MINIMUM_MEMORY_ADDRESS)
|
||||||
|
{
|
||||||
|
return pContext->ThrowNativeError("Invalid address 0x%x is pointing to reserved memory.", addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* data = *reinterpret_cast<void**>(addr);
|
||||||
|
if (pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
|
||||||
|
return pseudoAddr.ToPseudoAddress(data);
|
||||||
|
}
|
||||||
|
return reinterpret_cast<uintptr_t>(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static cell_t StoreAddressToAddress(IPluginContext *pContext, const cell_t *params)
|
||||||
|
{
|
||||||
|
void *addr = reinterpret_cast<void*>(params[1]);
|
||||||
|
if (pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
|
||||||
|
addr = pseudoAddr.FromPseudoAddress(params[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addr == NULL)
|
||||||
|
{
|
||||||
|
return pContext->ThrowNativeError("Address cannot be null");
|
||||||
|
}
|
||||||
|
else if (reinterpret_cast<uintptr_t>(addr) < VALID_MINIMUM_MEMORY_ADDRESS)
|
||||||
|
{
|
||||||
|
return pContext->ThrowNativeError("Invalid address 0x%x is pointing to reserved memory.", addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *data = reinterpret_cast<void*>(params[2]);
|
||||||
|
if (pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
|
||||||
|
data = pseudoAddr.FromPseudoAddress(params[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool updateMemAccess = params[3];
|
||||||
|
|
||||||
|
if (updateMemAccess) {
|
||||||
|
SourceHook::SetMemAccess(addr, sizeof(void*), SH_MEM_READ|SH_MEM_WRITE|SH_MEM_EXEC);
|
||||||
|
}
|
||||||
|
*reinterpret_cast<void**>(addr) = data;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static cell_t IsNullVector(IPluginContext *pContext, const cell_t *params)
|
static cell_t IsNullVector(IPluginContext *pContext, const cell_t *params)
|
||||||
{
|
{
|
||||||
cell_t *pNullVec = pContext->GetNullRef(SP_NULL_VECTOR);
|
cell_t *pNullVec = pContext->GetNullRef(SP_NULL_VECTOR);
|
||||||
@ -1157,6 +1209,8 @@ REGISTER_NATIVES(coreNatives)
|
|||||||
{"RequireFeature", RequireFeature},
|
{"RequireFeature", RequireFeature},
|
||||||
{"LoadFromAddress", LoadFromAddress},
|
{"LoadFromAddress", LoadFromAddress},
|
||||||
{"StoreToAddress", StoreToAddress},
|
{"StoreToAddress", StoreToAddress},
|
||||||
|
{"LoadAddressFromAddress", LoadAddressFromAddress},
|
||||||
|
{"StoreAddressToAddress", StoreAddressToAddress},
|
||||||
{"IsNullVector", IsNullVector},
|
{"IsNullVector", IsNullVector},
|
||||||
{"IsNullString", IsNullString},
|
{"IsNullString", IsNullString},
|
||||||
{"LogStackTrace", LogStackTrace},
|
{"LogStackTrace", LogStackTrace},
|
||||||
|
|||||||
@ -32,6 +32,7 @@
|
|||||||
#include "common_logic.h"
|
#include "common_logic.h"
|
||||||
#include <IHandleSys.h>
|
#include <IHandleSys.h>
|
||||||
#include "GameConfigs.h"
|
#include "GameConfigs.h"
|
||||||
|
#include "PseudoAddrManager.h"
|
||||||
|
|
||||||
HandleType_t g_GameConfigsType;
|
HandleType_t g_GameConfigsType;
|
||||||
|
|
||||||
@ -155,11 +156,10 @@ static cell_t smn_GameConfGetAddress(IPluginContext *pCtx, const cell_t *params)
|
|||||||
if (!gc->GetAddress(key, &val))
|
if (!gc->GetAddress(key, &val))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
#ifdef KE_ARCH_X86
|
if (pCtx->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
|
||||||
return (cell_t)val;
|
|
||||||
#else
|
|
||||||
return pseudoAddr.ToPseudoAddress(val);
|
return pseudoAddr.ToPseudoAddress(val);
|
||||||
#endif
|
}
|
||||||
|
return reinterpret_cast<uintptr_t>(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static cell_t smn_GameConfGetMemSig(IPluginContext *pCtx, const cell_t *params)
|
static cell_t smn_GameConfGetMemSig(IPluginContext *pCtx, const cell_t *params)
|
||||||
@ -187,11 +187,10 @@ static cell_t smn_GameConfGetMemSig(IPluginContext *pCtx, const cell_t *params)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef KE_ARCH_X86
|
if (pCtx->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
|
||||||
return (cell_t)val;
|
|
||||||
#else
|
|
||||||
return pseudoAddr.ToPseudoAddress(val);
|
return pseudoAddr.ToPseudoAddress(val);
|
||||||
#endif
|
}
|
||||||
|
return reinterpret_cast<uintptr_t>(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GameConfigsNatives s_GameConfigsNatives;
|
static GameConfigsNatives s_GameConfigsNatives;
|
||||||
|
|||||||
@ -724,11 +724,10 @@ static cell_t GetEntDataEnt2(IPluginContext *pContext, const cell_t *params)
|
|||||||
|
|
||||||
static cell_t LoadEntityFromHandleAddress(IPluginContext *pContext, const cell_t *params)
|
static cell_t LoadEntityFromHandleAddress(IPluginContext *pContext, const cell_t *params)
|
||||||
{
|
{
|
||||||
#ifdef KE_ARCH_X86
|
|
||||||
void *addr = reinterpret_cast<void*>(params[1]);
|
void *addr = reinterpret_cast<void*>(params[1]);
|
||||||
#else
|
if (pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
|
||||||
void *addr = g_SourceMod.FromPseudoAddress(params[1]);
|
addr = g_SourceMod.FromPseudoAddress(params[1]);
|
||||||
#endif
|
}
|
||||||
|
|
||||||
if (addr == NULL)
|
if (addr == NULL)
|
||||||
{
|
{
|
||||||
@ -835,11 +834,10 @@ static cell_t SetEntDataEnt2(IPluginContext *pContext, const cell_t *params)
|
|||||||
|
|
||||||
static cell_t StoreEntityToHandleAddress(IPluginContext *pContext, const cell_t *params)
|
static cell_t StoreEntityToHandleAddress(IPluginContext *pContext, const cell_t *params)
|
||||||
{
|
{
|
||||||
#ifdef KE_ARCH_X86
|
|
||||||
void *addr = reinterpret_cast<void*>(params[1]);
|
void *addr = reinterpret_cast<void*>(params[1]);
|
||||||
#else
|
if (pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
|
||||||
void *addr = g_SourceMod.FromPseudoAddress(params[1]);
|
addr = g_SourceMod.FromPseudoAddress(params[1]);
|
||||||
#endif
|
}
|
||||||
|
|
||||||
if (addr == NULL)
|
if (addr == NULL)
|
||||||
{
|
{
|
||||||
@ -2772,11 +2770,10 @@ static cell_t GetEntityAddress(IPluginContext *pContext, const cell_t *params)
|
|||||||
return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
|
return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef KE_ARCH_X86
|
if (pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
|
||||||
return reinterpret_cast<cell_t>(pEntity);
|
|
||||||
#else
|
|
||||||
return g_SourceMod.ToPseudoAddress(pEntity);
|
return g_SourceMod.ToPseudoAddress(pEntity);
|
||||||
#endif
|
}
|
||||||
|
return reinterpret_cast<uintptr_t>(pEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
REGISTER_NATIVES(entityNatives)
|
REGISTER_NATIVES(entityNatives)
|
||||||
|
|||||||
@ -376,7 +376,7 @@ ReturnAction_t HandleDetour(HookType_t hookType, CHook* pDetour)
|
|||||||
{
|
{
|
||||||
// The this pointer is implicitly always the first argument.
|
// The this pointer is implicitly always the first argument.
|
||||||
void *thisPtr = pDetour->GetArgument<void *>(0);
|
void *thisPtr = pDetour->GetArgument<void *>(0);
|
||||||
cell_t thisAddr = GetThisPtr(thisPtr, pWrapper->thisType);
|
cell_t thisAddr = GetThisPtr(pCallback->GetParentContext(), thisPtr, pWrapper->thisType);
|
||||||
pCallback->PushCell(thisAddr);
|
pCallback->PushCell(thisAddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -174,7 +174,12 @@ cell_t Native_CreateHook(IPluginContext *pContext, const cell_t *params)
|
|||||||
//native Handle:DHookCreateDetour(Address:funcaddr, CallingConvention:callConv, ReturnType:returntype, ThisPointerType:thistype);
|
//native Handle:DHookCreateDetour(Address:funcaddr, CallingConvention:callConv, ReturnType:returntype, ThisPointerType:thistype);
|
||||||
cell_t Native_CreateDetour(IPluginContext *pContext, const cell_t *params)
|
cell_t Native_CreateDetour(IPluginContext *pContext, const cell_t *params)
|
||||||
{
|
{
|
||||||
HookSetup *setup = new HookSetup((ReturnType)params[3], PASSFLAG_BYVAL, (CallingConvention)params[2], (ThisPointerType)params[4], (void *)params[1]);
|
void* addr = reinterpret_cast<void*>(params[1]);
|
||||||
|
if (pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
|
||||||
|
addr = g_pSM->FromPseudoAddress(params[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
HookSetup *setup = new HookSetup((ReturnType)params[3], PASSFLAG_BYVAL, (CallingConvention)params[2], (ThisPointerType)params[4], addr);
|
||||||
|
|
||||||
Handle_t hndl = handlesys->CreateHandle(g_HookSetupHandle, setup, pContext->GetIdentity(), myself->GetIdentity(), NULL);
|
Handle_t hndl = handlesys->CreateHandle(g_HookSetupHandle, setup, pContext->GetIdentity(), myself->GetIdentity(), NULL);
|
||||||
|
|
||||||
@ -641,7 +646,10 @@ cell_t HookRawImpl(IPluginContext *pContext, const cell_t *params, int callbackI
|
|||||||
if (removalcbIndex > 0)
|
if (removalcbIndex > 0)
|
||||||
removalcb = pContext->GetFunctionById(params[removalcbIndex]);
|
removalcb = pContext->GetFunctionById(params[removalcbIndex]);
|
||||||
|
|
||||||
void *iface = (void *)(params[3]);
|
void* iface = reinterpret_cast<void*>(params[3]);
|
||||||
|
if (pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
|
||||||
|
iface = g_pSM->FromPseudoAddress(params[3]);
|
||||||
|
}
|
||||||
|
|
||||||
for(int i = g_pHooks.size() -1; i >= 0; i--)
|
for(int i = g_pHooks.size() -1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
@ -1482,6 +1490,10 @@ cell_t Native_GetParamAddress(IPluginContext *pContext, const cell_t *params)
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t offset = GetParamOffset(paramStruct, index);
|
size_t offset = GetParamOffset(paramStruct, index);
|
||||||
|
|
||||||
|
if (pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
|
||||||
|
return g_pSM->ToPseudoAddress(*(void**)((intptr_t)paramStruct->orgParams + offset));
|
||||||
|
}
|
||||||
return *(cell_t *)((intptr_t)paramStruct->orgParams + offset);
|
return *(cell_t *)((intptr_t)paramStruct->orgParams + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -465,7 +465,7 @@ HookReturnStruct *GetReturnStruct(DHooksCallback *dg)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
cell_t GetThisPtr(void *iface, ThisPointerType type)
|
cell_t GetThisPtr(IPluginContext* pContext, void *iface, ThisPointerType type)
|
||||||
{
|
{
|
||||||
if (type == ThisPointer_CBaseEntity)
|
if (type == ThisPointer_CBaseEntity)
|
||||||
{
|
{
|
||||||
@ -473,11 +473,10 @@ cell_t GetThisPtr(void *iface, ThisPointerType type)
|
|||||||
return -1;
|
return -1;
|
||||||
return gamehelpers->EntityToBCompatRef((CBaseEntity *)iface);
|
return gamehelpers->EntityToBCompatRef((CBaseEntity *)iface);
|
||||||
}
|
}
|
||||||
#ifdef KE_ARCH_X64
|
if (pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
|
||||||
return g_pSM->ToPseudoAddress(iface);
|
return g_pSM->ToPseudoAddress(iface);
|
||||||
#else
|
}
|
||||||
return (cell_t)iface;
|
return (cell_t)iface;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined( WIN32 ) && !defined( KE_ARCH_X64 )
|
#if defined( WIN32 ) && !defined( KE_ARCH_X64 )
|
||||||
@ -500,7 +499,7 @@ void *Callback(DHooksCallback *dg, void **argStack)
|
|||||||
|
|
||||||
if(dg->thisType == ThisPointer_CBaseEntity || dg->thisType == ThisPointer_Address)
|
if(dg->thisType == ThisPointer_CBaseEntity || dg->thisType == ThisPointer_Address)
|
||||||
{
|
{
|
||||||
dg->plugin_callback->PushCell(GetThisPtr(g_SHPtr->GetIfacePtr(), dg->thisType));
|
dg->plugin_callback->PushCell(GetThisPtr(dg->plugin_callback->GetParentContext(), g_SHPtr->GetIfacePtr(), dg->thisType));
|
||||||
}
|
}
|
||||||
if(dg->returnType != ReturnType_Void)
|
if(dg->returnType != ReturnType_Void)
|
||||||
{
|
{
|
||||||
@ -684,7 +683,7 @@ float Callback_float(DHooksCallback *dg, void **argStack)
|
|||||||
|
|
||||||
if(dg->thisType == ThisPointer_CBaseEntity || dg->thisType == ThisPointer_Address)
|
if(dg->thisType == ThisPointer_CBaseEntity || dg->thisType == ThisPointer_Address)
|
||||||
{
|
{
|
||||||
dg->plugin_callback->PushCell(GetThisPtr(g_SHPtr->GetIfacePtr(), dg->thisType));
|
dg->plugin_callback->PushCell(GetThisPtr(dg->plugin_callback->GetParentContext(), g_SHPtr->GetIfacePtr(), dg->thisType));
|
||||||
}
|
}
|
||||||
|
|
||||||
returnStruct = GetReturnStruct(dg);
|
returnStruct = GetReturnStruct(dg);
|
||||||
@ -841,7 +840,7 @@ SDKVector *Callback_vector(DHooksCallback *dg, void **argStack)
|
|||||||
|
|
||||||
if(dg->thisType == ThisPointer_CBaseEntity || dg->thisType == ThisPointer_Address)
|
if(dg->thisType == ThisPointer_CBaseEntity || dg->thisType == ThisPointer_Address)
|
||||||
{
|
{
|
||||||
dg->plugin_callback->PushCell(GetThisPtr(g_SHPtr->GetIfacePtr(), dg->thisType));
|
dg->plugin_callback->PushCell(GetThisPtr(dg->plugin_callback->GetParentContext(), g_SHPtr->GetIfacePtr(), dg->thisType));
|
||||||
}
|
}
|
||||||
|
|
||||||
returnStruct = GetReturnStruct(dg);
|
returnStruct = GetReturnStruct(dg);
|
||||||
@ -995,7 +994,7 @@ string_t *Callback_stringt(DHooksCallback *dg, void **argStack)
|
|||||||
|
|
||||||
if(dg->thisType == ThisPointer_CBaseEntity || dg->thisType == ThisPointer_Address)
|
if(dg->thisType == ThisPointer_CBaseEntity || dg->thisType == ThisPointer_Address)
|
||||||
{
|
{
|
||||||
dg->plugin_callback->PushCell(GetThisPtr(g_SHPtr->GetIfacePtr(), dg->thisType));
|
dg->plugin_callback->PushCell(GetThisPtr(dg->plugin_callback->GetParentContext(), g_SHPtr->GetIfacePtr(), dg->thisType));
|
||||||
}
|
}
|
||||||
|
|
||||||
returnStruct = GetReturnStruct(dg);
|
returnStruct = GetReturnStruct(dg);
|
||||||
|
|||||||
@ -339,7 +339,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
size_t GetStackArgsSize(DHooksCallback *dg);
|
size_t GetStackArgsSize(DHooksCallback *dg);
|
||||||
cell_t GetThisPtr(void *iface, ThisPointerType type);
|
cell_t GetThisPtr(IPluginContext* pContext, void *iface, ThisPointerType type);
|
||||||
|
|
||||||
extern IBinTools *g_pBinTools;
|
extern IBinTools *g_pBinTools;
|
||||||
extern HandleType_t g_HookParamsHandle;
|
extern HandleType_t g_HookParamsHandle;
|
||||||
|
|||||||
@ -63,7 +63,8 @@ inline void DecodePassMethod(ValveType vtype, SDKPassMethod method, PassType &ty
|
|||||||
type = PassType_Basic;
|
type = PassType_Basic;
|
||||||
if (vtype == Valve_POD
|
if (vtype == Valve_POD
|
||||||
|| vtype == Valve_Float
|
|| vtype == Valve_Float
|
||||||
|| vtype == Valve_Bool)
|
|| vtype == Valve_Bool
|
||||||
|
|| vtype == Valve_VirtualAddress)
|
||||||
{
|
{
|
||||||
flags = PASSFLAG_BYVAL | PASSFLAG_ASPOINTER;
|
flags = PASSFLAG_BYVAL | PASSFLAG_ASPOINTER;
|
||||||
} else {
|
} else {
|
||||||
@ -86,6 +87,13 @@ inline void DecodePassMethod(ValveType vtype, SDKPassMethod method, PassType &ty
|
|||||||
|
|
||||||
static cell_t StartPrepSDKCall(IPluginContext *pContext, const cell_t *params)
|
static cell_t StartPrepSDKCall(IPluginContext *pContext, const cell_t *params)
|
||||||
{
|
{
|
||||||
|
auto call_type = (ValveCallType)params[1];
|
||||||
|
if (call_type == ValveCall_Raw && pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
|
||||||
|
return pContext->ThrowNativeError("SDKCall_Raw is unavailable for plugins that have enabled virtual address.");
|
||||||
|
}
|
||||||
|
if (call_type == ValveCall_VirtualAddress && pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) != SP_ERROR_NONE) {
|
||||||
|
return pContext->ThrowNativeError("SDKCall_VirtualAddress is unavailable for plugins that haven't enabled virtual address.");
|
||||||
|
}
|
||||||
s_numparams = 0;
|
s_numparams = 0;
|
||||||
s_vtbl_index = -1;
|
s_vtbl_index = -1;
|
||||||
s_call_addr = NULL;
|
s_call_addr = NULL;
|
||||||
@ -172,11 +180,10 @@ static cell_t PrepSDKCall_SetSignature(IPluginContext *pContext, const cell_t *p
|
|||||||
|
|
||||||
static cell_t PrepSDKCall_SetAddress(IPluginContext *pContext, const cell_t *params)
|
static cell_t PrepSDKCall_SetAddress(IPluginContext *pContext, const cell_t *params)
|
||||||
{
|
{
|
||||||
#ifdef KE_ARCH_X86
|
|
||||||
s_call_addr = reinterpret_cast<void*>(params[1]);
|
s_call_addr = reinterpret_cast<void*>(params[1]);
|
||||||
#else
|
if (pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
|
||||||
s_call_addr = g_pSM->FromPseudoAddress(params[1]);
|
s_call_addr = g_pSM->FromPseudoAddress(params[1]);
|
||||||
#endif
|
}
|
||||||
|
|
||||||
return (s_call_addr != NULL) ? 1 : 0;
|
return (s_call_addr != NULL) ? 1 : 0;
|
||||||
}
|
}
|
||||||
@ -413,6 +420,36 @@ static cell_t SDKCall(IPluginContext *pContext, const cell_t *params)
|
|||||||
startparam++;
|
startparam++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ValveCall_VirtualAddress:
|
||||||
|
{
|
||||||
|
//params[startparam] is an address to a pointer to THIS
|
||||||
|
//params following this are params to the method we will invoke later
|
||||||
|
if (startparam > numparams)
|
||||||
|
{
|
||||||
|
vc->stk_put(ptr);
|
||||||
|
return pContext->ThrowNativeError("Expected a ThisPtr address, it wasn't found");
|
||||||
|
}
|
||||||
|
|
||||||
|
//note: varargs pawn args are passed by-ref
|
||||||
|
cell_t *cell;
|
||||||
|
pContext->LocalToPhysAddr(params[startparam], &cell);
|
||||||
|
void* thisptr = reinterpret_cast<void*>(g_pSM->FromPseudoAddress(*cell));
|
||||||
|
|
||||||
|
if (thisptr == nullptr)
|
||||||
|
{
|
||||||
|
vc->stk_put(ptr);
|
||||||
|
return pContext->ThrowNativeError("ThisPtr address cannot be null");
|
||||||
|
}
|
||||||
|
else if (reinterpret_cast<uintptr_t>(thisptr) < VALID_MINIMUM_MEMORY_ADDRESS)
|
||||||
|
{
|
||||||
|
vc->stk_put(ptr);
|
||||||
|
return pContext->ThrowNativeError("Invalid ThisPtr address %p is pointing to reserved memory.", thisptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
*(void **)ptr = thisptr;
|
||||||
|
startparam++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
vc->stk_put(ptr);
|
vc->stk_put(ptr);
|
||||||
@ -536,6 +573,13 @@ static cell_t SDKCall(IPluginContext *pContext, const cell_t *params)
|
|||||||
addr = *(bool **)addr;
|
addr = *(bool **)addr;
|
||||||
}
|
}
|
||||||
return *addr ? 1 : 0;
|
return *addr ? 1 : 0;
|
||||||
|
} else if (vc->retinfo->vtype == Valve_VirtualAddress) {
|
||||||
|
void *addr = *(void **)vc->retbuf;
|
||||||
|
if (vc->retinfo->flags & PASSFLAG_ASPOINTER)
|
||||||
|
{
|
||||||
|
addr = *(void **)addr;
|
||||||
|
}
|
||||||
|
return g_pSM->ToPseudoAddress(addr);
|
||||||
} else {
|
} else {
|
||||||
cell_t *addr = (cell_t *)vc->retbuf;
|
cell_t *addr = (cell_t *)vc->retbuf;
|
||||||
if (vc->retinfo->flags & PASSFLAG_ASPOINTER)
|
if (vc->retinfo->flags & PASSFLAG_ASPOINTER)
|
||||||
|
|||||||
@ -164,6 +164,21 @@ size_t ValveParamToBinParam(ValveType type,
|
|||||||
return sizeof(float);
|
return sizeof(float);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case Valve_VirtualAddress:
|
||||||
|
{
|
||||||
|
info->flags = flags;
|
||||||
|
if (flags & PASSFLAG_ASPOINTER)
|
||||||
|
{
|
||||||
|
needs_extra = true;
|
||||||
|
info->type = PassType_Basic;
|
||||||
|
info->size = sizeof(void**);
|
||||||
|
return sizeof(void**) + sizeof(void*);
|
||||||
|
} else {
|
||||||
|
info->type = PassType_Basic;
|
||||||
|
info->size = sizeof(void*);
|
||||||
|
return sizeof(void*);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -276,6 +291,19 @@ DataStatus EncodeValveParam(IPluginContext *pContext,
|
|||||||
|
|
||||||
*addr = *(bool *)buffer ? 1 : 0;
|
*addr = *(bool *)buffer ? 1 : 0;
|
||||||
|
|
||||||
|
return Data_Okay;
|
||||||
|
}
|
||||||
|
case Valve_VirtualAddress:
|
||||||
|
{
|
||||||
|
cell_t *addr;
|
||||||
|
pContext->LocalToPhysAddr(param, &addr);
|
||||||
|
|
||||||
|
if (data->flags & PASSFLAG_ASPOINTER)
|
||||||
|
{
|
||||||
|
buffer = *(void **)buffer;
|
||||||
|
}
|
||||||
|
*addr = g_pSM->ToPseudoAddress(*(void**)buffer);
|
||||||
|
|
||||||
return Data_Okay;
|
return Data_Okay;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -585,6 +613,29 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
|
|||||||
*(char **)buffer = addr;
|
*(char **)buffer = addr;
|
||||||
return Data_Okay;
|
return Data_Okay;
|
||||||
}
|
}
|
||||||
|
case Valve_VirtualAddress:
|
||||||
|
{
|
||||||
|
if (data->decflags & VDECODE_FLAG_BYREF)
|
||||||
|
{
|
||||||
|
cell_t *addr;
|
||||||
|
pContext->LocalToPhysAddr(param, &addr);
|
||||||
|
param = *addr;
|
||||||
|
}
|
||||||
|
if (data->flags & PASSFLAG_ASPOINTER)
|
||||||
|
{
|
||||||
|
*(void **)buffer = (unsigned char *)_buffer + pCall->stackEnd + data->obj_offset;
|
||||||
|
buffer = *(void **)buffer;
|
||||||
|
}
|
||||||
|
void* addr = g_pSM->FromPseudoAddress(param);
|
||||||
|
if (addr == nullptr && (data->decflags & VDECODE_FLAG_ALLOWNULL) == 0)
|
||||||
|
{
|
||||||
|
pContext->ThrowNativeError("NULL Address not allowed");
|
||||||
|
return Data_Fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(void **)buffer = addr;
|
||||||
|
return Data_Okay;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Data_Fail;
|
return Data_Fail;
|
||||||
|
|||||||
@ -53,6 +53,7 @@ enum ValveType
|
|||||||
Valve_Edict, /**< Edict */
|
Valve_Edict, /**< Edict */
|
||||||
Valve_String, /**< String */
|
Valve_String, /**< String */
|
||||||
Valve_Bool, /**< Boolean */
|
Valve_Bool, /**< Boolean */
|
||||||
|
Valve_VirtualAddress, /**< SM Virtual Address */
|
||||||
Valve_Object, /**< Object, not matching one of the above types */
|
Valve_Object, /**< Object, not matching one of the above types */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -84,6 +85,7 @@ enum ValveCallType
|
|||||||
ValveCall_Raw, /**< Thiscall (address explicit first parameter) */
|
ValveCall_Raw, /**< Thiscall (address explicit first parameter) */
|
||||||
ValveCall_Server, /**< Thiscall (CBaseServer implicit first parameter) */
|
ValveCall_Server, /**< Thiscall (CBaseServer implicit first parameter) */
|
||||||
ValveCall_Engine, /**< Thiscall (CVEngineServer implicit first parameter) */
|
ValveCall_Engine, /**< Thiscall (CVEngineServer implicit first parameter) */
|
||||||
|
ValveCall_VirtualAddress /**< Thiscall (address explicit first parameter) */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -121,6 +121,13 @@
|
|||||||
"linux" "259"
|
"linux" "259"
|
||||||
"linux64" "259"
|
"linux64" "259"
|
||||||
}
|
}
|
||||||
|
"GetAttachment"
|
||||||
|
{
|
||||||
|
"windows" "211"
|
||||||
|
"windows64" "211"
|
||||||
|
"linux" "212"
|
||||||
|
"linux64" "212"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"Keys"
|
"Keys"
|
||||||
|
|||||||
@ -60,9 +60,10 @@ enum SDKCallType
|
|||||||
SDKCall_Player, /**< CBasePlayer call */
|
SDKCall_Player, /**< CBasePlayer call */
|
||||||
SDKCall_GameRules, /**< CGameRules call */
|
SDKCall_GameRules, /**< CGameRules call */
|
||||||
SDKCall_EntityList, /**< CGlobalEntityList call */
|
SDKCall_EntityList, /**< CGlobalEntityList call */
|
||||||
SDKCall_Raw, /**< |this| pointer with an arbitrary address */
|
SDKCall_Raw, /**< |this| pointer with an arbitrary address. This is not available if SM's virtual addresses are enabled */
|
||||||
SDKCall_Server, /**< CBaseServer call */
|
SDKCall_Server, /**< CBaseServer call */
|
||||||
SDKCall_Engine /**< CVEngineServer call */
|
SDKCall_Engine, /**< CVEngineServer call */
|
||||||
|
SDKCall_VirtualAddress /**< |this| pointer with an arbitrary SM virtual address */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum SDKLibrary
|
enum SDKLibrary
|
||||||
@ -88,7 +89,8 @@ enum SDKType
|
|||||||
SDKType_Float, /**< Float (any) */
|
SDKType_Float, /**< Float (any) */
|
||||||
SDKType_Edict, /**< edict_t (always as pointer) */
|
SDKType_Edict, /**< edict_t (always as pointer) */
|
||||||
SDKType_String, /**< NULL-terminated string (always as pointer) */
|
SDKType_String, /**< NULL-terminated string (always as pointer) */
|
||||||
SDKType_Bool /**< Boolean (any) */
|
SDKType_Bool, /**< Boolean (any) */
|
||||||
|
SDKType_VirtualAddress, /**< SM Virtual Address */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum SDKPassMethod
|
enum SDKPassMethod
|
||||||
|
|||||||
@ -754,6 +754,26 @@ native any LoadFromAddress(Address addr, NumberType size);
|
|||||||
*/
|
*/
|
||||||
native void StoreToAddress(Address addr, any data, NumberType size, bool updateMemAccess = true);
|
native void StoreToAddress(Address addr, any data, NumberType size, bool updateMemAccess = true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load sizeof(void*) from a memory address.
|
||||||
|
*
|
||||||
|
* @param addr Address to a memory location.
|
||||||
|
* @return The address that is stored at that address.
|
||||||
|
* @error Address is null or pointing to reserved memory.
|
||||||
|
*/
|
||||||
|
native Address LoadAddressFromAddress(Address addr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store sizeof(void*) bytes to a memory address.
|
||||||
|
*
|
||||||
|
* @param addr Address to a memory location.
|
||||||
|
* @param data Address to store at that location.
|
||||||
|
* @param updateMemAccess If true, SourceMod will set read / write / exec permissions
|
||||||
|
* on the memory page being written to.
|
||||||
|
* @error Address is null or pointing to reserved memory.
|
||||||
|
*/
|
||||||
|
native void StoreAddressToAddress(Address addr, Address data, bool updateMemAccess = true);
|
||||||
|
|
||||||
methodmap FrameIterator < Handle {
|
methodmap FrameIterator < Handle {
|
||||||
// Creates a stack frame iterator to build your own stack traces.
|
// Creates a stack frame iterator to build your own stack traces.
|
||||||
// @return New handle to a FrameIterator.
|
// @return New handle to a FrameIterator.
|
||||||
|
|||||||
39
plugins/include/virtual_address.inc
Normal file
39
plugins/include/virtual_address.inc
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* vim: set ts=4 :
|
||||||
|
* =============================================================================
|
||||||
|
* SourceMod (C)2004-2025 AlliedModders LLC. All rights reserved.
|
||||||
|
* =============================================================================
|
||||||
|
*
|
||||||
|
* This file is part of the SourceMod/SourcePawn SDK.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
|
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||||
|
* Free Software Foundation.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||||
|
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||||
|
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||||
|
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||||
|
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||||
|
* this exception to all derivative works. AlliedModders LLC defines further
|
||||||
|
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||||
|
* or <http://www.sourcemod.net/license.php>.
|
||||||
|
*
|
||||||
|
* Version: $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined _virtual_address_included
|
||||||
|
#endinput
|
||||||
|
#endif
|
||||||
|
#define _virtual_address_included
|
||||||
|
|
||||||
|
public const Address __Virtual_Address__ = view_as<Address>(0);
|
||||||
|
public const Address PointerSize = view_as<Address>(0); /**< Size of a pointer in bytes (same as `sizeof(void*)`) */
|
||||||
Loading…
Reference in New Issue
Block a user