Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a2b8d2a7e0 | |||
| 5dde1f641e | |||
| d6262135a8 | |||
| 83d85f5d5c | |||
| 5c61928260 | |||
| 722406fef2 | |||
| c9ba29f60b | |||
| 650825d793 | |||
| ce63965502 | |||
| dd04a4f480 | |||
| b5662b64ec | |||
| 3d821c41c3 | |||
| 39b0097ed2 | |||
| 232f37d762 | |||
| 762034301a | |||
| 9d5d7bd0d6 | |||
| f72686f27a | |||
| 3e5628f198 | |||
| 1cc0ca7e29 | |||
| cfc584ebfa | |||
| 1a0aad3223 | |||
| 368ae01c64 | |||
| b4f9cca516 | |||
| bb6e6b9236 | |||
| dde316a184 | |||
| 43df6fc452 | |||
| eff857398d | |||
| 091bd36858 | |||
| 8a8ea1e6e1 | |||
| ace2046ae8 | |||
| 1462cabed5 | |||
| b500f46d00 | |||
| ca209ae383 | |||
| ce7f57f412 |
@@ -0,0 +1,121 @@
|
||||
name: Build WeirdPerformance 2.4-B1 GC test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- test/wp24b-gc-safe-sweep
|
||||
paths:
|
||||
- 'experiments/wp24b-gc/**'
|
||||
- '.github/workflows/wp24b-gc.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: mlugg/setup-zig@v2
|
||||
with:
|
||||
version: '0.17.0-dev.1970+67f39b551'
|
||||
- name: Build and ABI-validate x86 DLL
|
||||
working-directory: experiments/wp24b-gc
|
||||
run: |
|
||||
set -euo pipefail
|
||||
zig build --fetch
|
||||
python3 - <<'PY'
|
||||
from pathlib import Path
|
||||
matches = list(Path("zig-pkg").glob("zhook-*/src/zhook.zig"))
|
||||
if len(matches) != 1:
|
||||
raise SystemExit(f"expected one pinned zhook source, found {len(matches)}")
|
||||
p = matches[0]
|
||||
text = p.read_text(encoding="utf-8")
|
||||
old = "var patch: [MAX_STOLEN]u8 = .{0x90} ** MAX_STOLEN;"
|
||||
new = "var patch: [MAX_STOLEN]u8 = @splat(0x90);"
|
||||
if old not in text:
|
||||
raise SystemExit("expected pinned zhook repeat initializer not found")
|
||||
p.write_text(text.replace(old, new), encoding="utf-8")
|
||||
PY
|
||||
|
||||
zig build -Doptimize=small
|
||||
DLL=zig-out/bin/weirdperformance_gc24b1.dll
|
||||
test -s "$DLL"
|
||||
file "$DLL" | tee BINARY_INFO.txt
|
||||
file "$DLL" | grep -Eq 'PE32.*Intel (80386|i386)'
|
||||
|
||||
if command -v llvm-objdump >/dev/null 2>&1; then
|
||||
llvm-objdump -d --x86-asm-syntax=intel "$DLL" > ABI_DISASM.txt
|
||||
else
|
||||
objdump -d -M intel "$DLL" > ABI_DISASM.txt
|
||||
fi
|
||||
|
||||
python3 - <<'PY'
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
asm = Path("ABI_DISASM.txt").read_text(encoding="utf-8", errors="replace").lower()
|
||||
|
||||
def require(pattern, label):
|
||||
if not re.search(pattern, asm, re.S):
|
||||
raise SystemExit(f"ABI validation failed: {label}")
|
||||
|
||||
# zhook must jump to callbacks compiled with L arriving in ECX.
|
||||
m = re.search(r"mov\s+edx,\s*0x6f7340.{0,240}?push\s+0x([0-9a-f]+)", asm, re.S)
|
||||
if not m:
|
||||
raise SystemExit("ABI validation failed: collector callback address not found")
|
||||
cb = m.group(1).lstrip("0") or "0"
|
||||
pos = asm.find(cb + ":")
|
||||
if pos < 0 or not re.search(r"mov\s+esi,\s*ecx", asm[pos:pos+500]):
|
||||
raise SystemExit("ABI validation failed: collector callback does not consume L from ECX")
|
||||
|
||||
m = re.search(r"mov\s+edx,\s*0x6f6ef0.{0,240}?push\s+0x([0-9a-f]+)", asm, re.S)
|
||||
if not m:
|
||||
raise SystemExit("ABI validation failed: lua_close callback address not found")
|
||||
cb = m.group(1).lstrip("0") or "0"
|
||||
pos = asm.find(cb + ":")
|
||||
if pos < 0 or not re.search(r"mov\s+esi,\s*ecx", asm[pos:pos+400]):
|
||||
raise SystemExit("ABI validation failed: lua_close callback does not consume L from ECX")
|
||||
|
||||
# Native helper ABI observed in WoW 5875:
|
||||
# ECX=L, EDX=&list, stack arg=all for 0x6F7210.
|
||||
require(
|
||||
r"lea\s+edx,\s*\[edi\s*\+\s*0x14\].{0,160}?"
|
||||
r"mov\s+eax,\s*0x6f7210.{0,120}?"
|
||||
r"mov\s+ecx,\s*esi.{0,120}?"
|
||||
r"push\s+0x0.{0,80}?call\s+eax",
|
||||
"lua_gc_remove_objects register/stack ABI",
|
||||
)
|
||||
|
||||
require(
|
||||
r"mov\s+eax,\s*0x6f72f0.{0,120}?"
|
||||
r"mov\s+ecx,\s*esi.{0,100}?"
|
||||
r"xor\s+edx,\s*edx.{0,80}?call\s+eax",
|
||||
"lua_gc_sweep_all_lists fastcall ABI",
|
||||
)
|
||||
|
||||
for addr, label in (
|
||||
("6f73e0", "lua_gc_full_collection"),
|
||||
("6f7370", "lua_gc_shrink_memory"),
|
||||
("6f7080", "luaCallUserDataGC"),
|
||||
):
|
||||
require(
|
||||
rf"mov\s+eax,\s*0x{addr}.{{0,120}}?mov\s+ecx,\s*esi.{{0,80}}?call\s+eax",
|
||||
f"{label} ECX ABI",
|
||||
)
|
||||
|
||||
print("ABI validation: PASS")
|
||||
PY
|
||||
|
||||
sha256sum "$DLL" | tee SHA256SUMS.txt
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: WeirdPerformance-2.4-B1-GC-Safe-Sweep
|
||||
path: |
|
||||
experiments/wp24b-gc/zig-out/bin/weirdperformance_gc24b1.dll
|
||||
experiments/wp24b-gc/SHA256SUMS.txt
|
||||
experiments/wp24b-gc/BINARY_INFO.txt
|
||||
experiments/wp24b-gc/ABI_DISASM.txt
|
||||
experiments/wp24b-gc/README.md
|
||||
if-no-files-found: error
|
||||
@@ -0,0 +1,131 @@
|
||||
name: Build WeirdPerformance 2.4-B2 GC reload-guard test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- test/wp24b2-gc-reload-guard
|
||||
paths:
|
||||
- 'experiments/wp24b-gc/**'
|
||||
- '.github/workflows/wp24b2-gc.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: mlugg/setup-zig@v2
|
||||
with:
|
||||
version: '0.17.0-dev.1970+67f39b551'
|
||||
- name: Build and ABI-validate x86 DLL
|
||||
working-directory: experiments/wp24b-gc
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
python3 b2_patch.py
|
||||
grep -q 'NATIVE_GRACE_COLLECTIONS: u32 = 3' main.zig
|
||||
grep -q '2.4-B2-gc-safe-sweep-reload-guard' main.zig
|
||||
grep -q 'weirdperformance_gc24b2' build.zig
|
||||
|
||||
zig build --fetch
|
||||
python3 - <<'PY'
|
||||
from pathlib import Path
|
||||
matches = list(Path("zig-pkg").glob("zhook-*/src/zhook.zig"))
|
||||
if len(matches) != 1:
|
||||
raise SystemExit(f"expected one pinned zhook source, found {len(matches)}")
|
||||
p = matches[0]
|
||||
text = p.read_text(encoding="utf-8")
|
||||
old = "var patch: [MAX_STOLEN]u8 = .{0x90} ** MAX_STOLEN;"
|
||||
new = "var patch: [MAX_STOLEN]u8 = @splat(0x90);"
|
||||
if old not in text:
|
||||
raise SystemExit("expected pinned zhook repeat initializer not found")
|
||||
p.write_text(text.replace(old, new), encoding="utf-8")
|
||||
PY
|
||||
|
||||
zig build -Doptimize=small
|
||||
DLL=zig-out/bin/weirdperformance_gc24b2.dll
|
||||
test -s "$DLL"
|
||||
file "$DLL" | tee BINARY_INFO.txt
|
||||
file "$DLL" | grep -Eq 'PE32.*Intel (80386|i386)'
|
||||
strings "$DLL" | grep -q '2.4-B2-gc-safe-sweep-reload-guard'
|
||||
|
||||
if command -v llvm-objdump >/dev/null 2>&1; then
|
||||
llvm-objdump -d --x86-asm-syntax=intel "$DLL" > ABI_DISASM.txt
|
||||
else
|
||||
objdump -d -M intel "$DLL" > ABI_DISASM.txt
|
||||
fi
|
||||
|
||||
python3 - <<'PY'
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
asm = Path("ABI_DISASM.txt").read_text(encoding="utf-8", errors="replace").lower()
|
||||
|
||||
def require(pattern, label):
|
||||
if not re.search(pattern, asm, re.S):
|
||||
raise SystemExit(f"ABI validation failed: {label}")
|
||||
|
||||
# zhook must jump to callbacks compiled with L arriving in ECX.
|
||||
m = re.search(r"mov\s+edx,\s*0x6f7340.{0,240}?push\s+0x([0-9a-f]+)", asm, re.S)
|
||||
if not m:
|
||||
raise SystemExit("ABI validation failed: collector callback address not found")
|
||||
cb = m.group(1).lstrip("0") or "0"
|
||||
pos = asm.find(cb + ":")
|
||||
if pos < 0 or not re.search(r"mov\s+esi,\s*ecx", asm[pos:pos+700]):
|
||||
raise SystemExit("ABI validation failed: collector callback does not consume L from ECX")
|
||||
|
||||
m = re.search(r"mov\s+edx,\s*0x6f6ef0.{0,240}?push\s+0x([0-9a-f]+)", asm, re.S)
|
||||
if not m:
|
||||
raise SystemExit("ABI validation failed: lua_close callback address not found")
|
||||
cb = m.group(1).lstrip("0") or "0"
|
||||
pos = asm.find(cb + ":")
|
||||
if pos < 0 or not re.search(r"mov\s+esi,\s*ecx", asm[pos:pos+500]):
|
||||
raise SystemExit("ABI validation failed: lua_close callback does not consume L from ECX")
|
||||
|
||||
# Native helper ABI observed in WoW 5875:
|
||||
# ECX=L, EDX=&list, stack arg=all for 0x6F7210.
|
||||
require(
|
||||
r"lea\s+edx,\s*\[edi\s*\+\s*0x14\].{0,160}?"
|
||||
r"mov\s+eax,\s*0x6f7210.{0,120}?"
|
||||
r"mov\s+ecx,\s*esi.{0,120}?"
|
||||
r"push\s+0x0.{0,80}?call\s+eax",
|
||||
"lua_gc_remove_objects register/stack ABI",
|
||||
)
|
||||
|
||||
require(
|
||||
r"mov\s+eax,\s*0x6f72f0.{0,120}?"
|
||||
r"mov\s+ecx,\s*esi.{0,100}?"
|
||||
r"xor\s+edx,\s*edx.{0,80}?call\s+eax",
|
||||
"lua_gc_sweep_all_lists fastcall ABI",
|
||||
)
|
||||
|
||||
for addr, label in (
|
||||
("6f73e0", "lua_gc_full_collection"),
|
||||
("6f7370", "lua_gc_shrink_memory"),
|
||||
("6f7080", "luaCallUserDataGC"),
|
||||
):
|
||||
require(
|
||||
rf"mov\s+eax,\s*0x{addr}.{{0,120}}?mov\s+ecx,\s*esi.{{0,80}}?call\s+eax",
|
||||
f"{label} ECX ABI",
|
||||
)
|
||||
|
||||
print("ABI validation: PASS")
|
||||
PY
|
||||
|
||||
sha256sum "$DLL" | tee SHA256SUMS.txt
|
||||
sha256sum main.zig build.zig b2_patch.py > PATCHED_SOURCE_SHA256.txt
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: WeirdPerformance-2.4-B2-GC-Reload-Guard
|
||||
path: |
|
||||
experiments/wp24b-gc/zig-out/bin/weirdperformance_gc24b2.dll
|
||||
experiments/wp24b-gc/SHA256SUMS.txt
|
||||
experiments/wp24b-gc/PATCHED_SOURCE_SHA256.txt
|
||||
experiments/wp24b-gc/BINARY_INFO.txt
|
||||
experiments/wp24b-gc/ABI_DISASM.txt
|
||||
experiments/wp24b-gc/README-B2.md
|
||||
experiments/wp24b-gc/b2_patch.py
|
||||
if-no-files-found: error
|
||||
@@ -0,0 +1,115 @@
|
||||
# WeirdUtils asset provenance
|
||||
|
||||
Audit date: 2026-08-31
|
||||
|
||||
No visual or font asset is intended to be modified during this documentation
|
||||
pass.
|
||||
|
||||
The root WeirdUtils public-domain dedication does **not** automatically apply
|
||||
to bundled third-party or game-facing assets.
|
||||
|
||||
## MinimapIcons assets
|
||||
|
||||
Path:
|
||||
|
||||
- `src/minimapicons/assets/`
|
||||
|
||||
Git tree SHA-1:
|
||||
|
||||
- `4d3848aa2ba1e32b8cfb5a8d4d67eaf4ead09e31`
|
||||
|
||||
The tracking directory contains 21 BLP resources under a game-style path:
|
||||
|
||||
- `Interface/Minimap/Tracking/`
|
||||
|
||||
Examples include `Banker.blp`, `FlightMaster.blp`,
|
||||
`QuestAvailable.blp`, `Repair.blp`, and `ObjectIcons.blp`.
|
||||
|
||||
Immediate repository provenance is known, but this audit does not establish
|
||||
the original creator or redistribution license of every underlying image.
|
||||
|
||||
## WorldMarkers assets
|
||||
|
||||
Path:
|
||||
|
||||
- `src/worldmarkers/assets/`
|
||||
|
||||
Known subtrees:
|
||||
|
||||
- `Spells/`:
|
||||
`5a3628820673332f3fdd481e80f3f6e81efed9e8`
|
||||
- `World/`:
|
||||
`9783e9c15f31a527c9d6f81e45b6c7ba251f27e3`
|
||||
|
||||
Files include game-facing names such as raid-target textures, spell/VFX
|
||||
textures, and resources under:
|
||||
|
||||
- `World/Expansion01/Doodads/Zulaman/Doors/`
|
||||
|
||||
These paths strongly indicate compatibility with game resource naming, but the
|
||||
documentation does not assert a specific extraction history without stronger
|
||||
evidence.
|
||||
|
||||
No ownership or public-domain claim is made over underlying Blizzard or other
|
||||
third-party artwork.
|
||||
|
||||
## WeirdDPSMate fonts
|
||||
|
||||
Path:
|
||||
|
||||
- `src/dpslog/WeirdDPSMate/fonts/`
|
||||
|
||||
Git tree SHA-1:
|
||||
|
||||
- `48374570b2c9659e1d781d4014c17fecd1b0f7f1`
|
||||
|
||||
The directory contains 13 TTF/OTF font files.
|
||||
|
||||
Their individual font licenses were not independently established during this
|
||||
audit. They are therefore not treated as public-domain material merely because
|
||||
they are bundled in WeirdUtils or inside the GPL-licensed DPSMate subtree.
|
||||
|
||||
## WeirdDPSMate images
|
||||
|
||||
Path:
|
||||
|
||||
- `src/dpslog/WeirdDPSMate/images/`
|
||||
|
||||
Git tree SHA-1:
|
||||
|
||||
- `bd649c1cffffc9b7d9b92fc001748531cb4ffa92`
|
||||
|
||||
The directory includes UI images, class icons, status-bar textures, and other
|
||||
TGA resources.
|
||||
|
||||
The immediate bundled provenance is documented, while underlying visual rights
|
||||
remain separate from the WeirdUtils root license.
|
||||
|
||||
## GraphLib textures
|
||||
|
||||
WeirdDPSMate also bundles GraphLib texture resources under:
|
||||
|
||||
- `src/dpslog/WeirdDPSMate/libs/GraphLib/GraphTextures/`
|
||||
|
||||
These include pie/line/triangle and related TGA resources. Their presence is
|
||||
not used to infer a new license from WeirdUtils.
|
||||
|
||||
## Rights boundary
|
||||
|
||||
World of Warcraft, Warcraft, Blizzard Entertainment, and associated names,
|
||||
marks, artwork, interface resources, client data, and game assets remain the
|
||||
property of their respective rights holders.
|
||||
|
||||
An exact Git tree or blob hash establishes file identity/provenance at a point
|
||||
in history. It does not by itself establish ownership or a right to relicense
|
||||
the underlying work.
|
||||
|
||||
## Maintenance
|
||||
|
||||
When assets are added, removed, or replaced:
|
||||
|
||||
1. record source and creation history where known;
|
||||
2. record hashes/tree identity where practical;
|
||||
3. preserve font/image license notices when available;
|
||||
4. do not place unresolved third-party/game-facing assets under the root
|
||||
public-domain dedication by implication.
|
||||
@@ -0,0 +1,76 @@
|
||||
# WeirdUtils binary and release provenance
|
||||
|
||||
Audit date: 2026-08-31
|
||||
|
||||
## Source repository
|
||||
|
||||
At the audited pre-documentation head
|
||||
`947056f1c22c4816f85038dfb78abe61c1e4133b`, the source tree contains no
|
||||
committed release `.dll` or `.exe` files.
|
||||
|
||||
Release DLLs are packaging/build outputs rather than checked-in binaries.
|
||||
|
||||
## GitHub Actions release workflow
|
||||
|
||||
`.github/workflows/release.yml` builds the standard public module DLLs with:
|
||||
|
||||
- Zig 0.16.0
|
||||
- target/build configuration defined by the repository source
|
||||
- `zig build all-variants -Doptimize=ReleaseSmall`
|
||||
|
||||
The workflow collects the generated DLLs and creates `SHA256SUMS.txt` before
|
||||
publishing release assets.
|
||||
|
||||
## WeirdPerformance release exception
|
||||
|
||||
The GitHub release workflow intentionally excludes the normal
|
||||
`weirdperformance` variant from the standard source build.
|
||||
|
||||
Instead, it downloads:
|
||||
|
||||
- `weirdperformance.dll`
|
||||
- from a Codeberg release under `Dusk92/WeirdUtils`
|
||||
- tag `0.7.3` as configured by
|
||||
`CUSTOM_WEIRDPERFORMANCE_TAG`
|
||||
|
||||
The workflow validates that the downloaded file has a plausible Windows PE
|
||||
header and then includes it in the generated SHA-256 manifest.
|
||||
|
||||
Therefore a GitHub WeirdUtils release is not composed exclusively of DLLs
|
||||
compiled in that same workflow: `weirdperformance.dll` is a separately
|
||||
sourced prebuilt release artifact.
|
||||
|
||||
This distinction should remain documented whenever the release workflow
|
||||
changes.
|
||||
|
||||
## Build-time zhook dependency
|
||||
|
||||
`build.zig.zon` pins zhook to:
|
||||
|
||||
- source:
|
||||
`https://codeberg.org/marcelinevq/zhook/archive/f1b252ed61ad839f00310c386761d068f293ad0f.tar.gz`
|
||||
- Zig package hash:
|
||||
`zhook-0.1.0-pFkSYC6FAACAnkqu0k_DJBWdL0gJjrM22IfXeQPJAMov`
|
||||
|
||||
The source is fetched during a build and is not vendored into this GitHub
|
||||
repository.
|
||||
|
||||
## Vendored libdeflate
|
||||
|
||||
`src/weirdperformance/libdeflate/` contains libdeflate source code (version
|
||||
1.25 according to the bundled header). The build compiles the required C files
|
||||
into the WeirdPerformance module.
|
||||
|
||||
libdeflate is MIT-licensed and is documented separately in
|
||||
`THIRD_PARTY_NOTICES.md` and `LICENSES/libdeflate-MIT.txt`.
|
||||
|
||||
## Release maintenance rule
|
||||
|
||||
For each release:
|
||||
|
||||
1. retain the exact source ref used for compiled DLLs;
|
||||
2. retain the source/tag of any prebuilt imported DLL;
|
||||
3. publish or retain SHA-256 checksums;
|
||||
4. keep third-party license records alongside the source project;
|
||||
5. do not describe a prebuilt imported artifact as compiled from the current
|
||||
GitHub commit unless that has actually been verified.
|
||||
@@ -0,0 +1,63 @@
|
||||
# WeirdUtils source provenance
|
||||
|
||||
Audit date: 2026-08-31
|
||||
|
||||
## Imported source history
|
||||
|
||||
The repository is not marked by GitHub as a fork, but its imported Git history
|
||||
contains extensive source development authored by MarcelineVQ.
|
||||
|
||||
The repository documentation points to the historical/source project at:
|
||||
|
||||
- https://codeberg.org/MarcelineVQ/WeirdUtils
|
||||
|
||||
## Dusk-92 GitHub maintenance boundary
|
||||
|
||||
A comparison was made from the last inspected MarcelineVQ-authored baseline:
|
||||
|
||||
- base: `41191ce9a5b50cf38fc48f138b8339ed17f9cae8`
|
||||
- pre-audit GitHub head:
|
||||
`947056f1c22c4816f85038dfb78abe61c1e4133b`
|
||||
|
||||
GitHub reports that the Dusk-92 head is four commits ahead of that baseline.
|
||||
|
||||
Only two paths differ in that comparison:
|
||||
|
||||
- `.github/workflows/release.yml`
|
||||
- `src/main.zig`
|
||||
|
||||
The relevant later commits are:
|
||||
|
||||
- `82dc02e2e78ca43496286c14a732a562d2448570`
|
||||
— Add automated DLL release workflow
|
||||
- `f4cbacb7f9e91f99e7409b3aa48a61fe6d96d978`
|
||||
— Fix DllMain return type for Zig 0.16
|
||||
- `c4d133887a9730e346d0654031cfeefb7a77e065`
|
||||
— Run release build CI on main and support source refs
|
||||
- `947056f1c22c4816f85038dfb78abe61c1e4133b`
|
||||
— Test full release packaging on main
|
||||
|
||||
This makes the authorship boundary unusually clear: the GitHub maintenance
|
||||
layer should not be presented as authorship of the entire imported WeirdUtils
|
||||
source tree.
|
||||
|
||||
## Third-party source boundaries
|
||||
|
||||
Known third-party or reference-derived areas include:
|
||||
|
||||
- `src/dpslog/WeirdDPSMate/` — DPSMate fork, GPL-3.0
|
||||
- `src/dpslog/WSBT/` — Mik/Athene material, license unresolved in this audit
|
||||
- `src/weirdperformance/libdeflate/` — libdeflate 1.25, MIT
|
||||
- `src/weirdperformance/timer_fix.zig` — ported from VanillaFixes, MIT
|
||||
- `src/ssemaths/math_sse.zig` — UnitXP_SP3 and libSiliconPatch references
|
||||
- external `zhook` build dependency — pinned in `build.zig.zon`
|
||||
|
||||
See `THIRD_PARTY_NOTICES.md`.
|
||||
|
||||
## Documentation-pass boundary
|
||||
|
||||
No Zig, C, Lua, XML, build workflow, BLP, TGA, font, or other runtime asset is
|
||||
intended to be modified by the 2026-08-31 licensing/provenance pass.
|
||||
|
||||
The final compare against the pre-audit head is the authoritative check for
|
||||
that statement.
|
||||
@@ -25,7 +25,57 @@ For more information, please refer to <https://unlicense.org/>
|
||||
|
||||
---
|
||||
|
||||
EXCEPTION: src/dpslog/WeirdDPSMate/ is a fork of DPSMate by Shino
|
||||
<Synced> and is licensed under the GNU General Public License v3.
|
||||
See src/dpslog/WeirdDPSMate/LICENSE. The dedication above does not
|
||||
apply to that directory.
|
||||
SCOPE AND THIRD-PARTY EXCEPTIONS
|
||||
|
||||
The public-domain dedication above applies only to material for which the
|
||||
applicable WeirdUtils author or authors hold the rights necessary to make that
|
||||
dedication.
|
||||
|
||||
It does not override or replace the copyright, license, trademark, or other
|
||||
rights applicable to third-party code, external dependencies, reference-derived
|
||||
material, fonts, artwork, game-facing resources, or other assets included in or
|
||||
referenced by this repository.
|
||||
|
||||
Known exclusions and separate terms include, without limitation:
|
||||
|
||||
1. src/dpslog/WeirdDPSMate/
|
||||
This is a fork of DPSMate by Shino <Synced> and is licensed under the GNU
|
||||
General Public License v3. See src/dpslog/WeirdDPSMate/LICENSE.
|
||||
|
||||
2. src/dpslog/WSBT/
|
||||
This contains historical Mik's Scrolling Battle Text / Combat Event Helper
|
||||
material credited to Mik and Athene. No standalone license for this bundled
|
||||
subtree was independently established during the 2026-08-31 audit. The
|
||||
public-domain dedication above does not claim to relicense it.
|
||||
|
||||
3. src/weirdperformance/libdeflate/
|
||||
This contains vendored libdeflate source under the MIT License. See
|
||||
LICENSES/libdeflate-MIT.txt.
|
||||
|
||||
4. VanillaFixes-derived material
|
||||
src/weirdperformance/timer_fix.zig explicitly identifies itself as ported
|
||||
from VanillaFixes, which is MIT-licensed. See
|
||||
LICENSES/VanillaFixes-MIT.txt.
|
||||
|
||||
5. External zhook dependency
|
||||
zhook is fetched at build time from its upstream Codeberg repository. It is
|
||||
not relicensed by this file.
|
||||
|
||||
6. UnitXP_SP3 / libSiliconPatch references
|
||||
Source comments identify these projects as behavioral, formula, or symbol
|
||||
references for some SSE work. This file does not make a public-domain claim
|
||||
over material whose applicable rights are held by those projects or other
|
||||
third parties.
|
||||
|
||||
7. Fonts, BLP/TGA artwork, and game-facing assets
|
||||
Bundled fonts and visual resources, including assets under minimapicons,
|
||||
worldmarkers, and WeirdDPSMate, remain subject to their respective rights.
|
||||
They are not placed in the public domain by this repository merely because
|
||||
they are included in the source tree.
|
||||
|
||||
See THIRD_PARTY_NOTICES.md, PROJECT_IDENTITY.md, Docs/, and LICENSES/ for the
|
||||
current provenance and scope record.
|
||||
|
||||
World of Warcraft, Warcraft, Blizzard Entertainment, and associated names,
|
||||
marks, artwork, client data, and game assets remain the property of their
|
||||
respective rights holders.
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
# Third-party license records
|
||||
|
||||
The root `LICENSE` contains the WeirdUtils public-domain dedication, but its
|
||||
scope is limited to material for which the applicable WeirdUtils authors have
|
||||
the rights to make that dedication.
|
||||
|
||||
Third-party material keeps its own terms.
|
||||
|
||||
## Preserved records
|
||||
|
||||
- `libdeflate-MIT.txt`
|
||||
- applies to vendored `src/weirdperformance/libdeflate/`
|
||||
- upstream: https://github.com/ebiggers/libdeflate
|
||||
|
||||
- `VanillaFixes-MIT.txt`
|
||||
- relevant to the timer implementation explicitly ported from VanillaFixes
|
||||
- upstream: https://github.com/hannesmann/vanillafixes
|
||||
|
||||
## Existing in-tree license
|
||||
|
||||
- `../src/dpslog/WeirdDPSMate/LICENSE`
|
||||
- GNU GPL v3
|
||||
- applies to the WeirdDPSMate / DPSMate code as documented by that subtree
|
||||
|
||||
## Unresolved / external
|
||||
|
||||
The 2026-08-31 audit did not independently establish a project-wide license
|
||||
for:
|
||||
|
||||
- bundled `src/dpslog/WSBT/` material;
|
||||
- `brues-code/UnitXP_SP3`, used as a behavior/formula reference;
|
||||
- the externally fetched Codeberg `zhook` dependency.
|
||||
|
||||
No license is invented for those components.
|
||||
|
||||
See `../THIRD_PARTY_NOTICES.md` for scope and provenance.
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Hannes Mann
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,22 @@
|
||||
Copyright 2016 Eric Biggers
|
||||
Copyright 2024 Google LLC
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation files
|
||||
(the "Software"), to deal in the Software without restriction,
|
||||
including without limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,51 @@
|
||||
# WeirdUtils project identity
|
||||
|
||||
## Current maintained GitHub repository
|
||||
|
||||
The current GitHub repository maintained and packaged by Dusk-92 is:
|
||||
|
||||
- https://github.com/Dusk-92/WeirdUtils
|
||||
|
||||
The source history in this repository substantially predates the GitHub
|
||||
packaging work and contains development by MarcelineVQ. The historical/source
|
||||
project referenced by the repository is:
|
||||
|
||||
- https://codeberg.org/MarcelineVQ/WeirdUtils
|
||||
|
||||
A mirror, release package, or compatibility target does not imply that its
|
||||
maintainer authored every component present in the tree.
|
||||
|
||||
## Independent community project
|
||||
|
||||
WeirdUtils is an independent community project for the World of Warcraft
|
||||
1.12.1 client.
|
||||
|
||||
It is not affiliated with, sponsored by, approved by, or endorsed by Blizzard
|
||||
Entertainment, Turtle WoW, OctoWoW, SuperWoW, DPSMate, MikScrollingBattleText,
|
||||
VanillaFixes, UnitXP_SP3, libdeflate, or any other referenced project unless
|
||||
explicitly stated by that party.
|
||||
|
||||
Compatibility and reverse-engineering references do not imply endorsement,
|
||||
partnership, ownership, or official status.
|
||||
|
||||
World of Warcraft, Warcraft, Blizzard Entertainment, and associated names,
|
||||
marks, artwork, client data, and game assets remain the property of their
|
||||
respective rights holders.
|
||||
|
||||
## Maintainer boundary
|
||||
|
||||
The imported Git history identifies MarcelineVQ as the principal author of the
|
||||
source project prior to the GitHub packaging work.
|
||||
|
||||
Dusk-92's GitHub-specific commits after the imported source baseline primarily
|
||||
cover release automation/packaging and a small Zig 0.16 compatibility change.
|
||||
|
||||
See `Docs/SOURCE_PROVENANCE.md` for the exact comparison.
|
||||
|
||||
## Support boundary
|
||||
|
||||
Dusk-92 is responsible only for the GitHub releases, packaging choices, and
|
||||
changes published from the maintained GitHub repository.
|
||||
|
||||
Third-party authors and compatibility-target projects are not responsible for
|
||||
this packaging or for downstream modifications.
|
||||
@@ -1,6 +1,6 @@
|
||||
# WeirdUtils
|
||||
|
||||
> **This project is no longer actively developed.** The full source is published here, in the public domain (see `LICENSE`), so it can be forked, salvaged, or learned from rather than bit-rotting on a private disk. See [Source Code](#source-code) for details and caveats.
|
||||
> **This project is no longer actively developed.** Project-authored source is published under the public-domain dedication in `LICENSE`, subject to the documented third-party code and asset exceptions. See [Source Code](#source-code) and [Licensing & provenance](#licensing--provenance) for details.
|
||||
|
||||
This package provides many pre-built DLLs for enhancing the vanilla 1.12 client WoW gameplay experience, aimed in particular at ease of use and accessibility but also bug fixes.
|
||||
|
||||
@@ -261,12 +261,15 @@ Most noticeable in cities, raids, during zone transitions, and in addon-heavy se
|
||||
|
||||
## Source Code
|
||||
|
||||
This project is no longer actively developed. The full source is now published here,
|
||||
in the public domain (see `LICENSE`), so it can be forked, salvaged, or learned from
|
||||
rather than bit-rotting on a private disk.
|
||||
This project is no longer actively developed. Project-authored source is published
|
||||
under the public-domain dedication in `LICENSE`, subject to the documented
|
||||
third-party code, dependency, font, and asset exceptions.
|
||||
|
||||
Earlier releases shipped as pre-built DLLs only. That is no longer the case - the
|
||||
binaries on the releases page and the source in this repo are the same project.
|
||||
Earlier releases shipped as pre-built DLLs only. Standard public module DLLs are now
|
||||
compiled from source by the GitHub release workflow. The current workflow treats
|
||||
`weirdperformance.dll` specially: it imports the configured Dusk92 Codeberg v0.7.3
|
||||
prebuilt and includes it in the generated SHA-256 manifest. See
|
||||
`Docs/BINARY_PROVENANCE.md` for the exact release boundary.
|
||||
|
||||
Fair warning to anyone building on this: these DLLs hook deeply into the client's
|
||||
internals - memory layout, function addresses, rendering pipeline, input handling.
|
||||
@@ -301,10 +304,37 @@ running under Wine/DXVK. Per-module build flags are listed by `zig build --help`
|
||||
| `docs/`, `src/*/RESEARCH.md` | Reverse-engineering notes for the subsystems being hooked |
|
||||
|
||||
`src/dpslog/WeirdDPSMate/` is a fork of DPSMate and stays under GPL-3.0 - see its
|
||||
own `LICENSE`. Everything else is unlicensed/public domain.
|
||||
own `LICENSE`. Other documented third-party code, dependencies, fonts, visual
|
||||
assets, and reference-derived material retain their own rights or unresolved status;
|
||||
the root public-domain dedication does not override them.
|
||||
|
||||
---
|
||||
|
||||
## Licensing & provenance
|
||||
|
||||
The root `LICENSE` public-domain dedication applies only to material for which the
|
||||
applicable WeirdUtils authors have the rights to make that dedication.
|
||||
|
||||
Important separate boundaries include:
|
||||
|
||||
- **WeirdDPSMate / DPSMate** — GPL-3.0.
|
||||
- **libdeflate 1.25** — vendored under the MIT License.
|
||||
- **VanillaFixes-derived timer work** — upstream MIT notice preserved.
|
||||
- **WSBT / Mik material** — bundled historical third-party code; no standalone
|
||||
license was independently established in this audit.
|
||||
- **zhook** — external pinned build dependency from Codeberg, not vendored here.
|
||||
- **BLP/TGA/fonts and game-facing resources** — not placed in the public domain
|
||||
merely by inclusion in this repository.
|
||||
|
||||
For the full record, see:
|
||||
|
||||
- [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)
|
||||
- [PROJECT_IDENTITY.md](PROJECT_IDENTITY.md)
|
||||
- [Docs/SOURCE_PROVENANCE.md](Docs/SOURCE_PROVENANCE.md)
|
||||
- [Docs/BINARY_PROVENANCE.md](Docs/BINARY_PROVENANCE.md)
|
||||
- [Docs/ASSET_PROVENANCE.md](Docs/ASSET_PROVENANCE.md)
|
||||
- [LICENSES/](LICENSES/)
|
||||
|
||||
## Developer Notes
|
||||
### Runtime Module Control API
|
||||
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
# WeirdUtils third-party notices
|
||||
|
||||
Audit date: 2026-08-31
|
||||
|
||||
The root `LICENSE` contains a public-domain dedication for WeirdUtils-authored
|
||||
material. That dedication does **not** override the licenses or rights of
|
||||
third-party code, assets, fonts, game-derived media, or reference material.
|
||||
|
||||
## Source project history
|
||||
|
||||
The Git history imported into this repository contains substantial development
|
||||
by MarcelineVQ and references the source project at:
|
||||
|
||||
- https://codeberg.org/MarcelineVQ/WeirdUtils
|
||||
|
||||
The later Dusk-92 GitHub commits are documented separately in
|
||||
`Docs/SOURCE_PROVENANCE.md`.
|
||||
|
||||
## libdeflate
|
||||
|
||||
Vendored path:
|
||||
|
||||
- `src/weirdperformance/libdeflate/`
|
||||
|
||||
The bundled headers identify libdeflate version 1.25.
|
||||
|
||||
Upstream:
|
||||
|
||||
- https://github.com/ebiggers/libdeflate
|
||||
|
||||
License:
|
||||
|
||||
- MIT
|
||||
- Copyright 2016 Eric Biggers
|
||||
- Copyright 2024 Google LLC
|
||||
|
||||
A verbatim copy of the upstream license is preserved at:
|
||||
|
||||
- `LICENSES/libdeflate-MIT.txt`
|
||||
|
||||
The WeirdUtils public-domain dedication does not replace libdeflate's MIT
|
||||
notice.
|
||||
|
||||
## VanillaFixes
|
||||
|
||||
The performance timer implementation explicitly identifies itself as:
|
||||
|
||||
- `src/weirdperformance/timer_fix.zig`
|
||||
- "ported from VanillaFixes"
|
||||
|
||||
Upstream:
|
||||
|
||||
- https://github.com/hannesmann/vanillafixes
|
||||
|
||||
License:
|
||||
|
||||
- MIT
|
||||
- Copyright (c) 2022 Hannes Mann
|
||||
|
||||
A verbatim copy is preserved at:
|
||||
|
||||
- `LICENSES/VanillaFixes-MIT.txt`
|
||||
|
||||
## WeirdDPSMate / DPSMate
|
||||
|
||||
Bundled path:
|
||||
|
||||
- `src/dpslog/WeirdDPSMate/`
|
||||
|
||||
The subtree identifies DPSMate as originally by Shino <Synced> - Kronos, with
|
||||
later contributors including Torio.
|
||||
|
||||
License:
|
||||
|
||||
- GNU General Public License v3
|
||||
|
||||
The authoritative license is already bundled at:
|
||||
|
||||
- `src/dpslog/WeirdDPSMate/LICENSE`
|
||||
|
||||
The root public-domain dedication does not apply to this subtree.
|
||||
|
||||
The subtree also contains fonts, images, GraphLib textures, and bundled
|
||||
libraries. The presence of the DPSMate GPL file is not used here to make an
|
||||
unsupported claim about the separate underlying rights of every font or visual
|
||||
asset. See `Docs/ASSET_PROVENANCE.md`.
|
||||
|
||||
## WSBT / Mik's Scrolling Battle Text material
|
||||
|
||||
Bundled path:
|
||||
|
||||
- `src/dpslog/WSBT/`
|
||||
|
||||
The source headers identify:
|
||||
|
||||
- Title: Mik's Combat Event Helper / Mik's Scrolling Battle Text
|
||||
- Author: Mik
|
||||
- Maintainer: Athene
|
||||
|
||||
No standalone license file was identified in this bundled WSBT subtree during
|
||||
this audit.
|
||||
|
||||
Accordingly, the WeirdUtils public-domain dedication does not claim to
|
||||
relicense this inherited material. Its exact licensing status remains
|
||||
unresolved unless stronger upstream evidence is later preserved.
|
||||
|
||||
## zhook
|
||||
|
||||
Build dependency:
|
||||
|
||||
- https://codeberg.org/marcelinevq/zhook
|
||||
- pinned commit: `f1b252ed61ad839f00310c386761d068f293ad0f`
|
||||
- Zig package hash:
|
||||
`zhook-0.1.0-pFkSYC6FAACAnkqu0k_DJBWdL0gJjrM22IfXeQPJAMov`
|
||||
|
||||
`build.zig.zon` downloads zhook at build time; it is not committed as a
|
||||
vendored source tree in this repository.
|
||||
|
||||
Its license was not independently verified during this GitHub-focused audit.
|
||||
The WeirdUtils root license therefore makes no licensing claim over zhook.
|
||||
|
||||
## UnitXP_SP3 reference material
|
||||
|
||||
`src/ssemaths/math_sse.zig` explicitly identifies
|
||||
`brues-code/UnitXP_SP3/polyfill.cpp` as a reference source for some function
|
||||
behavior and formulas.
|
||||
|
||||
Reference repository:
|
||||
|
||||
- https://github.com/brues-code/UnitXP_SP3
|
||||
|
||||
No root project-wide license file was identified in UnitXP_SP3 during this
|
||||
audit. Reference provenance is preserved without asserting that UnitXP_SP3
|
||||
material is public domain under WeirdUtils' root license.
|
||||
|
||||
## libSiliconPatch reference
|
||||
|
||||
The SSE research comments also identify libSiliconPatch as a closed-source
|
||||
symbol/export reference.
|
||||
|
||||
No libSiliconPatch binary is identified as a vendored dependency in the
|
||||
WeirdUtils source tree. Reference to its symbols or behavior does not imply
|
||||
ownership, affiliation, or a right to relicense that project.
|
||||
|
||||
## Game-facing visual assets
|
||||
|
||||
WeirdUtils bundles BLP/TGA assets under areas including:
|
||||
|
||||
- `src/minimapicons/assets/`
|
||||
- `src/worldmarkers/assets/`
|
||||
- `src/dpslog/WeirdDPSMate/images/`
|
||||
- `src/dpslog/WeirdDPSMate/libs/GraphLib/GraphTextures/`
|
||||
|
||||
It also bundles fonts under:
|
||||
|
||||
- `src/dpslog/WeirdDPSMate/fonts/`
|
||||
|
||||
These materials are excluded from the root public-domain dedication unless a
|
||||
specific file's rights are independently established.
|
||||
|
||||
Some paths and filenames correspond closely to World of Warcraft client
|
||||
resource naming. This provenance audit does not claim that Dusk-92 or
|
||||
MarcelineVQ owns the underlying Blizzard or third-party artwork.
|
||||
|
||||
See `Docs/ASSET_PROVENANCE.md`.
|
||||
|
||||
## SuperWoW and server compatibility
|
||||
|
||||
WeirdUtils contains compatibility logic and references for SuperWoW and
|
||||
community-server environments.
|
||||
|
||||
Compatibility does not imply affiliation or endorsement. SuperWoW itself is
|
||||
not relicensed by WeirdUtils.
|
||||
|
||||
## World of Warcraft / Blizzard
|
||||
|
||||
World of Warcraft, Warcraft, Blizzard Entertainment, and associated names,
|
||||
marks, artwork, client data, and game assets remain the property of their
|
||||
respective rights holders.
|
||||
|
||||
## Preservation rule
|
||||
|
||||
When third-party material is updated, replaced, or removed:
|
||||
|
||||
1. preserve its source and attribution;
|
||||
2. preserve the applicable license or permission where known;
|
||||
3. do not expand the root public-domain dedication to material whose rights are
|
||||
not held by WeirdUtils contributors;
|
||||
4. keep provenance records even when a component stops being bundled.
|
||||
@@ -0,0 +1,53 @@
|
||||
# WeirdPerformance 2.4-B2 — GC Safe Sweep Reload Guard
|
||||
|
||||
Strict A/B experiment for WoW 1.12.1 build 5875.
|
||||
|
||||
## Baseline
|
||||
|
||||
Keep the validated 2.4-A binary unchanged:
|
||||
|
||||
- `weirdperformance.dll`
|
||||
- SHA-256: `d35168ae06c19087ef9b7c68918a054640396dfbfcef0664e18e9372284b5eef`
|
||||
|
||||
## B2 variant
|
||||
|
||||
Add:
|
||||
|
||||
- `weirdperformance_gc24b2.dll`
|
||||
|
||||
B2 is generated from the ABI-fixed B1 source with one isolated behavioral change:
|
||||
|
||||
- whenever a new Lua `global_State` is observed (initial world entry, `/reload`, logout/relog), the first **3 GC collections stay fully native**;
|
||||
- after those 3 native collections, the exact B1 incremental rootgc safe-sweep behavior resumes.
|
||||
|
||||
Nothing else is changed: same 50,000-object chunk size, same native mark/userdata/string work, same birth-mark ownership checks, same `lua_close` reconnect safety, same `IS_IN_WORLD` guard, no allocator changes, no generational age bitmap, no write barriers, no profiling/RDTSC.
|
||||
|
||||
The B2 delta is applied reproducibly by `b2_patch.py`; the build fails if any expected B1 source anchor no longer matches.
|
||||
|
||||
## Why this test exists
|
||||
|
||||
A delayed crash can be caused by corruption that happened earlier, so the crashing stack does not have to contain the GC companion. B2 specifically reduces risk during Lua state recreation without changing the core GC experiment.
|
||||
|
||||
## Installation
|
||||
|
||||
Keep both DLLs next to WoW and list both in `dlls.txt`:
|
||||
|
||||
```text
|
||||
weirdperformance.dll
|
||||
weirdperformance_gc24b2.dll
|
||||
```
|
||||
|
||||
Remove `weirdperformance_gc24b1.dll` while testing B2. Never load B1 and B2 together.
|
||||
|
||||
Removing `weirdperformance_gc24b2.dll` returns exactly to the validated 2.4-A baseline.
|
||||
|
||||
## First test
|
||||
|
||||
1. Launch and enter the world.
|
||||
2. Play normally for 10–15 minutes.
|
||||
3. Do one `/reload`, then wait and play for several minutes.
|
||||
4. If clean, do 10 `/reload` total.
|
||||
5. Then test logout/relog and character changes.
|
||||
6. Keep all other DLLs/addons/settings unchanged for the A/B comparison.
|
||||
|
||||
If an ERROR #132 occurs, keep both `Crash.txt` and `Crash.dmp` and note what happened shortly before the crash.
|
||||
@@ -0,0 +1,46 @@
|
||||
# WeirdPerformance 2.4-B1 — GC Safe Sweep ABI-fixed test
|
||||
|
||||
Strict A/B experiment for WoW 1.12.1 build 5875.
|
||||
|
||||
## Baseline
|
||||
|
||||
Keep the validated 2.4-A binary **unchanged**:
|
||||
|
||||
- `weirdperformance.dll`
|
||||
- SHA-256: `d35168ae06c19087ef9b7c68918a054640396dfbfcef0664e18e9372284b5eef`
|
||||
|
||||
## B1 variant
|
||||
|
||||
Add:
|
||||
|
||||
- `weirdperformance_gc24b1.dll`
|
||||
|
||||
The companion changes **only Lua GC behavior**. It does not replace or rebuild the validated 2.4-A DLL.
|
||||
|
||||
The first 2.4-B build is invalid and must not be used. It was built with an i386 Windows fastcall ABI mismatch and crashed at startup in WoW's native `lua_gc_remove_objects`. B1 is built with a pinned Zig 0.17 development toolchain and is binary-disassembly checked for the expected register ABI before distribution.
|
||||
|
||||
The implementation is based on the historical pre-generational incremental sweep: WoW keeps its native mark, userdata/string sweep, memory shrink and finalizers. Only the main `rootgc` sweep is split into 50,000-object chunks.
|
||||
|
||||
## Safety scope
|
||||
|
||||
- hooks only `luaC_collectgarbage` and `lua_close`;
|
||||
- no overlap with the lifecycle hooks referenced by the validated 2.4-A binary;
|
||||
- any fragmented sweep is reconnected before native `lua_close` destroys the Lua state;
|
||||
- GC calls made from inside `lua_close` stay native;
|
||||
- the birth-mark byte is ownership checked and restored only while still owned;
|
||||
- a changed Lua `global_State` forces native fallback rather than reconnecting stale pointers;
|
||||
- hook installation is transactional;
|
||||
- no generational age bitmap, no write barriers, no GC tuning, no profiling/RDTSC.
|
||||
|
||||
## Installation for the test
|
||||
|
||||
Keep both DLLs next to WoW and list both in `dlls.txt`:
|
||||
|
||||
```text
|
||||
weirdperformance.dll
|
||||
weirdperformance_gc24b1.dll
|
||||
```
|
||||
|
||||
Delete the old `weirdperformance_gc24b.dll` if it is still present.
|
||||
|
||||
Removing `weirdperformance_gc24b1.dll` returns you exactly to the validated 2.4-A baseline.
|
||||
@@ -0,0 +1,79 @@
|
||||
from pathlib import Path
|
||||
|
||||
root = Path(__file__).resolve().parent
|
||||
main_path = root / "main.zig"
|
||||
build_path = root / "build.zig"
|
||||
|
||||
main = main_path.read_text(encoding="utf-8")
|
||||
build = build_path.read_text(encoding="utf-8")
|
||||
|
||||
replacements = [
|
||||
(
|
||||
"const BATCH_HEADROOM: u32 = 128 * 1024;\n",
|
||||
"const BATCH_HEADROOM: u32 = 128 * 1024;\n"
|
||||
"const NATIVE_GRACE_COLLECTIONS: u32 = 3;\n",
|
||||
),
|
||||
(
|
||||
"var installed = false;\nvar in_gc = false;\nvar closing_lua = false;\n",
|
||||
"var installed = false;\nvar in_gc = false;\nvar closing_lua = false;\n"
|
||||
"var active_g: u32 = 0;\n"
|
||||
"var native_grace_collections: u32 = 0;\n",
|
||||
),
|
||||
(
|
||||
" // Never carry private list state into another Lua global_State.\n"
|
||||
" if (sweeping and g != saved_g) {\n"
|
||||
" resetSweepState();\n"
|
||||
" collect_hook.callOriginal(.{L});\n"
|
||||
" return;\n"
|
||||
" }\n\n"
|
||||
" // If another module changed the birth byte during our split cycle,\n",
|
||||
" // Never carry private list state into another Lua global_State.\n"
|
||||
" if (sweeping and g != saved_g) {\n"
|
||||
" resetSweepState();\n"
|
||||
" collect_hook.callOriginal(.{L});\n"
|
||||
" return;\n"
|
||||
" }\n\n"
|
||||
" // B2: when a fresh Lua global_State appears (initial world entry,\n"
|
||||
" // /reload, logout/relog), keep the first three collections fully\n"
|
||||
" // native. This gives WoW ownership of the fragile state-rebuild\n"
|
||||
" // window before incremental rootgc sweeping resumes.\n"
|
||||
" if (active_g != g) {\n"
|
||||
" active_g = g;\n"
|
||||
" native_grace_collections = NATIVE_GRACE_COLLECTIONS;\n"
|
||||
" }\n"
|
||||
" if (native_grace_collections != 0) {\n"
|
||||
" native_grace_collections -= 1;\n"
|
||||
" collect_hook.callOriginal(.{L});\n"
|
||||
" return;\n"
|
||||
" }\n\n"
|
||||
" // If another module changed the birth byte during our split cycle,\n",
|
||||
),
|
||||
(
|
||||
" reconnectSweep();\n in_gc = false;\n\n lua_close_hook.callOriginal(.{L});\n",
|
||||
" reconnectSweep();\n in_gc = false;\n"
|
||||
" active_g = 0;\n"
|
||||
" native_grace_collections = 0;\n\n"
|
||||
" lua_close_hook.callOriginal(.{L});\n",
|
||||
),
|
||||
(
|
||||
'const version: [*:0]const u8 = "2.4-B1-gc-safe-sweep-abi";\n',
|
||||
'const version: [*:0]const u8 = "2.4-B2-gc-safe-sweep-reload-guard";\n',
|
||||
),
|
||||
]
|
||||
|
||||
for old, new in replacements:
|
||||
count = main.count(old)
|
||||
if count != 1:
|
||||
raise SystemExit(f"main.zig patch anchor mismatch: expected 1, found {count}: {old[:80]!r}")
|
||||
main = main.replace(old, new, 1)
|
||||
|
||||
old_name = '.name = "weirdperformance_gc24b1",'
|
||||
new_name = '.name = "weirdperformance_gc24b2",'
|
||||
if build.count(old_name) != 1:
|
||||
raise SystemExit("build.zig output-name anchor mismatch")
|
||||
build = build.replace(old_name, new_name, 1)
|
||||
|
||||
main_path.write_text(main, encoding="utf-8")
|
||||
build_path.write_text(build, encoding="utf-8")
|
||||
|
||||
print("B2 patch applied: new-global_State native grace = 3 GC cycles")
|
||||
@@ -0,0 +1,30 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const target = b.resolveTargetQuery(.{
|
||||
.cpu_arch = .x86,
|
||||
.os_tag = .windows,
|
||||
.abi = .msvc,
|
||||
.cpu_features_add = std.Target.x86.featureSet(&.{ .sse, .sse2 }),
|
||||
});
|
||||
const optimize = b.option(std.builtin.OptimizeMode, "optimize", "Optimization mode") orelse .small;
|
||||
|
||||
const zhook_dep = b.dependency("zhook", .{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
|
||||
const lib = b.addLibrary(.{
|
||||
.name = "weirdperformance_gc24b1",
|
||||
.linkage = .dynamic,
|
||||
.root_module = b.createModule(.{
|
||||
.root_source_file = b.path("main.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.imports = &.{
|
||||
.{ .name = "zhook", .module = zhook_dep.module("zhook") },
|
||||
},
|
||||
}),
|
||||
});
|
||||
b.installArtifact(lib);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
.{
|
||||
.name = .weirdperformance_gc24b,
|
||||
.version = "2.4.0",
|
||||
.fingerprint = 0x95e8be635406d50f,
|
||||
.dependencies = .{
|
||||
.zhook = .{
|
||||
.url = "https://codeberg.org/marcelinevq/zhook/archive/f1b252ed61ad839f00310c386761d068f293ad0f.tar.gz",
|
||||
.hash = "zhook-0.1.0-pFkSYC6FAACAnkqu0k_DJBWdL0gJjrM22IfXeQPJAMov",
|
||||
},
|
||||
},
|
||||
.paths = .{
|
||||
"build.zig",
|
||||
"build.zig.zon",
|
||||
"main.zig",
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,364 @@
|
||||
//! WeirdPerformance 2.4-B GC safe-sweep companion.
|
||||
//!
|
||||
//! A/B contract:
|
||||
//! A = validated WeirdPerformance 2.4-A binary, unchanged.
|
||||
//! B = the exact same 2.4-A binary + this companion DLL.
|
||||
//!
|
||||
//! This companion only changes Lua GC behavior: WoW's native mark/udata/string
|
||||
//! work is kept, while the rootgc sweep is split into bounded chunks.
|
||||
//!
|
||||
//! Target: WoW 1.12.1 build 5875, x86 only.
|
||||
|
||||
const std = @import("std");
|
||||
const hook = @import("zhook");
|
||||
const WINAPI = std.builtin.CallingConvention.winapi;
|
||||
const X86_FASTCALL: std.builtin.CallingConvention = .{ .x86_fastcall = .{} };
|
||||
|
||||
const LUA_COLLECT_GARBAGE_ADDR: usize = 0x6F7340;
|
||||
const LUA_CLOSE_ADDR: usize = 0x6F6EF0;
|
||||
const BIRTH_MARK_ADDR: usize = 0x6F7B37;
|
||||
const IS_IN_WORLD_ADDR: u32 = 0x00B4B424;
|
||||
|
||||
const GS_ROOTGC: u32 = 0x10;
|
||||
const GS_ROOTUDATA: u32 = 0x14;
|
||||
const GS_GCTHRESHOLD: u32 = 0x24;
|
||||
const GS_TOTALBYTES: u32 = 0x28;
|
||||
const OBJ_NEXT: u32 = 0;
|
||||
|
||||
const CHUNK_SIZE: u32 = 50_000;
|
||||
const BATCH_HEADROOM: u32 = 128 * 1024;
|
||||
|
||||
// Crash logs for the supported client show 0x00400000..0x00D2B000.
|
||||
const EXPECTED_IMAGE_BASE: usize = 0x00400000;
|
||||
const EXPECTED_IMAGE_SIZE: u32 = 0x0092B000;
|
||||
|
||||
const CollectFn = fn (u32) callconv(X86_FASTCALL) void;
|
||||
const LuaCloseFn = fn (u32) callconv(X86_FASTCALL) void;
|
||||
const SweepAllFn = fn (u32, u32) callconv(X86_FASTCALL) void;
|
||||
const RemoveObjectsFn = fn (u32, u32, u32) callconv(X86_FASTCALL) u32;
|
||||
|
||||
const lua_gc_full_collection: *const CollectFn = @ptrFromInt(0x6F73E0);
|
||||
const lua_gc_shrink_memory: *const CollectFn = @ptrFromInt(0x6F7370);
|
||||
const luaCallUserDataGC: *const CollectFn = @ptrFromInt(0x6F7080);
|
||||
const lua_gc_sweep_all_lists: *const SweepAllFn = @ptrFromInt(0x6F72F0);
|
||||
const lua_gc_remove_objects: *const RemoveObjectsFn = @ptrFromInt(0x6F7210);
|
||||
|
||||
var collect_hook: hook.Detour(CollectFn) = .{};
|
||||
var lua_close_hook: hook.Detour(LuaCloseFn) = .{};
|
||||
|
||||
var installed = false;
|
||||
var in_gc = false;
|
||||
var closing_lua = false;
|
||||
|
||||
var sweeping = false;
|
||||
var swept_head: u32 = 0;
|
||||
var swept_tail: u32 = 0;
|
||||
var unswept_rest: u32 = 0;
|
||||
var saved_g: u32 = 0;
|
||||
|
||||
var birth_mark_owned = false;
|
||||
var birth_mark_original: u8 = 0;
|
||||
|
||||
inline fn readU8(addr: usize) u8 {
|
||||
return @as(*volatile const u8, @ptrFromInt(addr)).*;
|
||||
}
|
||||
|
||||
inline fn readU16(addr: usize) u16 {
|
||||
return @as(*volatile const u16, @ptrFromInt(addr)).*;
|
||||
}
|
||||
|
||||
inline fn readU32(addr: u32) u32 {
|
||||
return @as(*volatile const u32, @ptrFromInt(addr)).*;
|
||||
}
|
||||
|
||||
inline fn readU32usize(addr: usize) u32 {
|
||||
return @as(*volatile const u32, @ptrFromInt(addr)).*;
|
||||
}
|
||||
|
||||
inline fn writeU32(addr: u32, value: u32) void {
|
||||
@as(*volatile u32, @ptrFromInt(addr)).* = value;
|
||||
}
|
||||
|
||||
inline fn getGlobalState(L: u32) u32 {
|
||||
return readU32(L + 0x10);
|
||||
}
|
||||
|
||||
fn validateClient() bool {
|
||||
if (readU16(EXPECTED_IMAGE_BASE) != 0x5A4D) return false; // MZ
|
||||
|
||||
const pe_off = readU32usize(EXPECTED_IMAGE_BASE + 0x3C);
|
||||
const pe = EXPECTED_IMAGE_BASE + pe_off;
|
||||
if (readU32usize(pe) != 0x00004550) return false; // PE\0\0
|
||||
if (readU16(pe + 4) != 0x014C) return false; // IMAGE_FILE_MACHINE_I386
|
||||
if (readU16(pe + 24) != 0x010B) return false; // PE32 optional header
|
||||
|
||||
const image_size = readU32usize(pe + 24 + 56);
|
||||
return image_size == EXPECTED_IMAGE_SIZE;
|
||||
}
|
||||
|
||||
fn findNth(head: u32, n: u32) struct { obj: u32, count: u32 } {
|
||||
var obj = head;
|
||||
var i: u32 = 0;
|
||||
while (obj != 0 and i < n) : (i += 1) {
|
||||
const next = readU32(obj + OBJ_NEXT);
|
||||
if (next == 0) return .{ .obj = 0, .count = i + 1 };
|
||||
obj = next;
|
||||
}
|
||||
return .{ .obj = obj, .count = i };
|
||||
}
|
||||
|
||||
fn findTail(head: u32) u32 {
|
||||
var obj = head;
|
||||
if (obj == 0) return 0;
|
||||
while (true) {
|
||||
const next = readU32(obj + OBJ_NEXT);
|
||||
if (next == 0) return obj;
|
||||
obj = next;
|
||||
}
|
||||
}
|
||||
|
||||
fn acquireBirthMark() bool {
|
||||
if (birth_mark_owned) return readU8(BIRTH_MARK_ADDR) == 0x01;
|
||||
|
||||
const current = readU8(BIRTH_MARK_ADDR);
|
||||
if (current != 0x00) return false;
|
||||
|
||||
birth_mark_original = current;
|
||||
const patch = [1]u8{0x01};
|
||||
hook.writeProtected(BIRTH_MARK_ADDR, &patch);
|
||||
|
||||
if (readU8(BIRTH_MARK_ADDR) != 0x01) return false;
|
||||
birth_mark_owned = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
fn releaseBirthMark() void {
|
||||
if (!birth_mark_owned) return;
|
||||
|
||||
// Restore only while we still own exactly the byte we installed.
|
||||
if (readU8(BIRTH_MARK_ADDR) == 0x01) {
|
||||
const patch = [1]u8{birth_mark_original};
|
||||
hook.writeProtected(BIRTH_MARK_ADDR, &patch);
|
||||
}
|
||||
birth_mark_owned = false;
|
||||
}
|
||||
|
||||
fn resetSweepState() void {
|
||||
sweeping = false;
|
||||
swept_head = 0;
|
||||
swept_tail = 0;
|
||||
unswept_rest = 0;
|
||||
saved_g = 0;
|
||||
releaseBirthMark();
|
||||
}
|
||||
|
||||
fn reconnectSweep() void {
|
||||
if (!sweeping or saved_g == 0) {
|
||||
resetSweepState();
|
||||
return;
|
||||
}
|
||||
|
||||
const g = saved_g;
|
||||
var tail = findTail(readU32(g + GS_ROOTGC));
|
||||
|
||||
if (unswept_rest != 0) {
|
||||
if (tail != 0) {
|
||||
writeU32(tail + OBJ_NEXT, unswept_rest);
|
||||
} else {
|
||||
writeU32(g + GS_ROOTGC, unswept_rest);
|
||||
}
|
||||
tail = findTail(unswept_rest);
|
||||
}
|
||||
|
||||
if (swept_head != 0) {
|
||||
if (tail != 0) {
|
||||
writeU32(tail + OBJ_NEXT, swept_head);
|
||||
} else {
|
||||
writeU32(g + GS_ROOTGC, swept_head);
|
||||
}
|
||||
}
|
||||
|
||||
resetSweepState();
|
||||
}
|
||||
|
||||
fn detachSweptAndRestore(g: u32) void {
|
||||
const current_head = readU32(g + GS_ROOTGC);
|
||||
if (current_head != 0) {
|
||||
const tail = findTail(current_head);
|
||||
if (swept_head == 0) {
|
||||
swept_head = current_head;
|
||||
swept_tail = tail;
|
||||
} else {
|
||||
writeU32(swept_tail + OBJ_NEXT, current_head);
|
||||
swept_tail = tail;
|
||||
}
|
||||
}
|
||||
|
||||
writeU32(g + GS_ROOTGC, unswept_rest);
|
||||
unswept_rest = 0;
|
||||
}
|
||||
|
||||
fn nativeFallback(L: u32) void {
|
||||
reconnectSweep();
|
||||
collect_hook.callOriginal(.{L});
|
||||
}
|
||||
|
||||
fn collectGarbageDetour(L: u32) callconv(X86_FASTCALL) void {
|
||||
if (closing_lua) {
|
||||
collect_hook.callOriginal(.{L});
|
||||
return;
|
||||
}
|
||||
|
||||
// Keep GlueXML/login/character-select on WoW's native GC.
|
||||
// The experiment is intentionally gameplay-only.
|
||||
if (readU32(IS_IN_WORLD_ADDR) == 0) {
|
||||
collect_hook.callOriginal(.{L});
|
||||
return;
|
||||
}
|
||||
if (in_gc) return;
|
||||
if (L == 0) return;
|
||||
if (readU32(L + 0x60) == 0) return;
|
||||
|
||||
in_gc = true;
|
||||
defer in_gc = false;
|
||||
|
||||
const g = getGlobalState(L);
|
||||
if (g == 0) {
|
||||
collect_hook.callOriginal(.{L});
|
||||
return;
|
||||
}
|
||||
|
||||
// Never carry private list state into another Lua global_State.
|
||||
if (sweeping and g != saved_g) {
|
||||
resetSweepState();
|
||||
collect_hook.callOriginal(.{L});
|
||||
return;
|
||||
}
|
||||
|
||||
// If another module changed the birth byte during our split cycle,
|
||||
// reconnect immediately and hand this collection back to WoW.
|
||||
if (sweeping and (!birth_mark_owned or readU8(BIRTH_MARK_ADDR) != 0x01)) {
|
||||
nativeFallback(L);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sweeping) {
|
||||
// Keep WoW's native mark, userdata sweep, and string sweep.
|
||||
lua_gc_full_collection(L);
|
||||
_ = lua_gc_remove_objects(L, g + GS_ROOTUDATA, 0);
|
||||
lua_gc_sweep_all_lists(L, 0);
|
||||
|
||||
swept_head = 0;
|
||||
swept_tail = 0;
|
||||
|
||||
const rootgc_head = readU32(g + GS_ROOTGC);
|
||||
const result = findNth(rootgc_head, CHUNK_SIZE);
|
||||
|
||||
// Small rootgc lists remain one-shot, matching native behavior closely.
|
||||
if (result.obj == 0) {
|
||||
_ = lua_gc_remove_objects(L, g + GS_ROOTGC, 0);
|
||||
lua_gc_shrink_memory(L);
|
||||
luaCallUserDataGC(L);
|
||||
return;
|
||||
}
|
||||
|
||||
// If the birth marker is unavailable, do not split this collection.
|
||||
if (!acquireBirthMark()) {
|
||||
_ = lua_gc_remove_objects(L, g + GS_ROOTGC, 0);
|
||||
lua_gc_shrink_memory(L);
|
||||
luaCallUserDataGC(L);
|
||||
return;
|
||||
}
|
||||
|
||||
unswept_rest = readU32(result.obj + OBJ_NEXT);
|
||||
writeU32(result.obj + OBJ_NEXT, 0);
|
||||
sweeping = true;
|
||||
saved_g = g;
|
||||
|
||||
_ = lua_gc_remove_objects(L, g + GS_ROOTGC, 0);
|
||||
detachSweptAndRestore(g);
|
||||
|
||||
const totalbytes = readU32(g + GS_TOTALBYTES);
|
||||
writeU32(g + GS_GCTHRESHOLD, totalbytes + BATCH_HEADROOM);
|
||||
return;
|
||||
}
|
||||
|
||||
const rootgc_head = readU32(g + GS_ROOTGC);
|
||||
const result = findNth(rootgc_head, CHUNK_SIZE);
|
||||
|
||||
if (result.obj == 0) {
|
||||
_ = lua_gc_remove_objects(L, g + GS_ROOTGC, 0);
|
||||
|
||||
const current_head = readU32(g + GS_ROOTGC);
|
||||
if (swept_head != 0) {
|
||||
if (current_head != 0) {
|
||||
writeU32(swept_tail + OBJ_NEXT, current_head);
|
||||
}
|
||||
writeU32(g + GS_ROOTGC, swept_head);
|
||||
}
|
||||
|
||||
resetSweepState();
|
||||
lua_gc_shrink_memory(L);
|
||||
luaCallUserDataGC(L);
|
||||
return;
|
||||
}
|
||||
|
||||
unswept_rest = readU32(result.obj + OBJ_NEXT);
|
||||
writeU32(result.obj + OBJ_NEXT, 0);
|
||||
|
||||
_ = lua_gc_remove_objects(L, g + GS_ROOTGC, 0);
|
||||
detachSweptAndRestore(g);
|
||||
|
||||
const totalbytes = readU32(g + GS_TOTALBYTES);
|
||||
writeU32(g + GS_GCTHRESHOLD, totalbytes + BATCH_HEADROOM);
|
||||
}
|
||||
|
||||
fn luaCloseDetour(L: u32) callconv(X86_FASTCALL) void {
|
||||
// lua_close may run native sweep paths that bypass luaC_collectgarbage.
|
||||
// Reconnect every private fragment while the old Lua state is still valid.
|
||||
closing_lua = true;
|
||||
reconnectSweep();
|
||||
in_gc = false;
|
||||
|
||||
lua_close_hook.callOriginal(.{L});
|
||||
|
||||
closing_lua = false;
|
||||
}
|
||||
|
||||
fn install() void {
|
||||
if (installed) return;
|
||||
if (!validateClient()) return;
|
||||
|
||||
// Transactional install: lua_close guard first, collector second.
|
||||
// If the collector cannot attach, roll the close hook back immediately.
|
||||
if (lua_close_hook.attach(LUA_CLOSE_ADDR, &luaCloseDetour) != .ok) return;
|
||||
|
||||
if (collect_hook.attach(LUA_COLLECT_GARBAGE_ADDR, &collectGarbageDetour) != .ok) {
|
||||
lua_close_hook.detach();
|
||||
return;
|
||||
}
|
||||
|
||||
installed = true;
|
||||
}
|
||||
|
||||
const version: [*:0]const u8 = "2.4-B1-gc-safe-sweep-abi";
|
||||
|
||||
pub export fn WeirdPerformanceGC24B_GetVersion() callconv(.c) [*:0]const u8 {
|
||||
return version;
|
||||
}
|
||||
|
||||
pub export fn WeirdPerformanceGC24B_IsActive() callconv(.c) i32 {
|
||||
return if (installed) 1 else 0;
|
||||
}
|
||||
|
||||
pub export fn DllMain(
|
||||
_: ?*anyopaque,
|
||||
reason: u32,
|
||||
_: ?*anyopaque,
|
||||
) callconv(WINAPI) std.os.windows.BOOL {
|
||||
if (reason == 1) install();
|
||||
|
||||
// Process-lifetime A/B companion. We intentionally do not hot-unhook
|
||||
// detours during process teardown.
|
||||
return @enumFromInt(1);
|
||||
}
|
||||
Reference in New Issue
Block a user