257 lines
9.8 KiB
YAML
257 lines
9.8 KiB
YAML
name: Test safe standalone core V8 Debug
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- test/safe-core-v8-debug
|
|
workflow_dispatch:
|
|
|
|
# V8 debug diagnostics build
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
build:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: mlugg/setup-zig@v2
|
|
with:
|
|
version: 0.16.0
|
|
|
|
- name: Build safe standalone variants
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
zig build all-variants -Doptimize=ReleaseSmall \
|
|
-Dweirdperformance=false \
|
|
-Doutline=true
|
|
|
|
- name: Verify minimal core layout
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
python3 - <<'PY'
|
|
from pathlib import Path
|
|
|
|
root = Path("zig-out/variants")
|
|
|
|
addr = {
|
|
"lua_protection": 0x42A320,
|
|
"register_commands": 0x490250,
|
|
"glue_commands": 0x46ABB0,
|
|
"engine_init": 0x46A400,
|
|
"logout": 0x491180,
|
|
"shutdown": 0x490BD0,
|
|
"file_fallback": 0x648620,
|
|
"open_file": 0x6477C0,
|
|
"file_size": 0x6487F0,
|
|
"read_file": 0x648460,
|
|
"cleanup_file": 0x648730,
|
|
"model_load": 0x71D4E0,
|
|
"check_file": 0x654DD0,
|
|
}
|
|
|
|
def has(data, value):
|
|
return value.to_bytes(4, "little") in data
|
|
|
|
outline = (root / "outline.dll").read_bytes()
|
|
custom = (root / "customassets.dll").read_bytes()
|
|
transmog = (root / "transmogfix.dll").read_bytes()
|
|
|
|
# Outline: only its Lua registration + engine init core hooks are allowed.
|
|
required_outline = ("register_commands", "engine_init")
|
|
forbidden_outline = tuple(k for k in addr if k not in required_outline)
|
|
for k in required_outline:
|
|
if not has(outline, addr[k]):
|
|
raise SystemExit(f"outline.dll missing required {k}")
|
|
bad = [k for k in forbidden_outline if has(outline, addr[k])]
|
|
if bad:
|
|
raise SystemExit(f"outline.dll still contains unwanted core hooks: {bad}")
|
|
print("outline.dll: minimal core verified")
|
|
|
|
# CustomAssets: only CheckFileExistence is allowed from the generic core.
|
|
if not has(custom, addr["check_file"]):
|
|
raise SystemExit("customassets.dll missing CheckFileExistence")
|
|
bad = [k for k,v in addr.items() if k != "check_file" and has(custom, v)]
|
|
if bad:
|
|
raise SystemExit(f"customassets.dll still contains unwanted core hooks: {bad}")
|
|
print("customassets.dll: minimal core verified")
|
|
|
|
# TransmogFix: none of the generic core hook target addresses should remain.
|
|
bad = [k for k,v in addr.items() if has(transmog, v)]
|
|
if bad:
|
|
raise SystemExit(f"transmogfix.dll still contains unwanted core hooks: {bad}")
|
|
print("transmogfix.dll: minimal core verified")
|
|
|
|
# Compatibility repair must exist in customassets and outline.
|
|
for name, data in (("outline.dll", outline), ("customassets.dll", custom)):
|
|
for gate in (0x654B5C, 0x654B6A):
|
|
if not has(data, gate):
|
|
raise SystemExit(f"{name} missing MPQ gate restore address 0x{gate:X}")
|
|
for seq in (bytes([0x74,0x25]), bytes([0x75,0x17])):
|
|
if seq not in data:
|
|
raise SystemExit(f"{name} missing original MPQ branch bytes {seq.hex()}")
|
|
print("legacy MPQ gate repair verified")
|
|
PY
|
|
|
|
- name: Verify Outline registration + Lua ABI
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
python3 - <<'PY'
|
|
from pathlib import Path
|
|
|
|
main = Path("src/main.zig").read_text()
|
|
outline = Path("src/outline/outline.zig").read_text()
|
|
d3d9 = Path("src/outline/d3d9_hook.zig").read_text()
|
|
|
|
if 'DEBUG14: do NOT force a D3D9 Reset here.' not in d3d9:
|
|
raise SystemExit("Missing DEBUG14 no-reset isolation in d3d9_hook.zig")
|
|
|
|
for required in (
|
|
'noinline fn registerFunction',
|
|
'0x704120',
|
|
'"{ecx}" (@intFromPtr(name))',
|
|
'"{edx}" (func_addr)',
|
|
):
|
|
if required not in main:
|
|
raise SystemExit(f"Missing explicit FrameScript registration ABI piece: {required}")
|
|
|
|
for required in (
|
|
'luaGetTopNative',
|
|
'luaIsStringNative',
|
|
'luaToStringNative',
|
|
'luaPushBooleanNative',
|
|
'"{ecx}"',
|
|
'"{edx}"',
|
|
'0x6F39F0',
|
|
'callconv(.{ .x86_thiscall = .{} })',
|
|
'luaPushStringNative',
|
|
'pub fn outlineDebug',
|
|
'OutlineDBG rh=',
|
|
'debug_unit_player_guid_seen',
|
|
'debug_unit_target_guid_seen',
|
|
'tracker.setDebugPinnedObjects(player_obj, target_obj)',
|
|
'debug_pin_target_consumed_seen',
|
|
'debug_scan_called_seen',
|
|
'debug_scan_after_publish_seen',
|
|
'getLiveHookState()',
|
|
'lateRehookIfLost()',
|
|
'debug_shader_stage',
|
|
'debug_resource_stage',
|
|
'endscene_ours',
|
|
'dip_ours',
|
|
'reset_ours',
|
|
):
|
|
if required not in outline:
|
|
raise SystemExit(f"Missing Outline callback/native wrapper ABI piece: {required}")
|
|
|
|
print("source: FrameScript registration uses ECX/EDX; Outline callback receives L in ECX")
|
|
PY
|
|
|
|
objdump -d -Mintel zig-out/variants/outline.dll > /tmp/outline.disasm
|
|
python3 - <<'PY'
|
|
import re
|
|
from pathlib import Path
|
|
|
|
lines = Path("/tmp/outline.disasm").read_text(errors="replace").splitlines()
|
|
|
|
# registerFunction is explicit inline asm and source-checked above.
|
|
# Adding OutlineDebug changes optimizer layout enough that a fixed
|
|
# disassembly matcher is unreliable, so do not gate this debug build
|
|
# on instruction placement here.
|
|
|
|
# OutlineCommand must capture the Lua state from ECX. Search function
|
|
# prologues for the characteristic saved-ESI form and reject the old
|
|
# [ebp+8] capture used by the cdecl experiment.
|
|
good_callback = False
|
|
for i, line in enumerate(lines):
|
|
if re.search(r"push\s+ebp\b", line, re.I):
|
|
block = "\n".join(lines[i:i + 12])
|
|
if re.search(r"mov\s+esi,ecx\b", block, re.I):
|
|
good_callback = True
|
|
break
|
|
|
|
if not good_callback:
|
|
raise SystemExit("BAD ABI: no callback body captures Lua state from ECX")
|
|
|
|
print("outline.dll machine code: registration and callback ABIs verified")
|
|
PY
|
|
|
|
- name: Verify direct player and target GUID path
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
python3 - <<'PY'
|
|
from pathlib import Path
|
|
wow = Path("src/wow.zig").read_text()
|
|
offsets = Path("src/offsets.zig").read_text()
|
|
for required in (
|
|
'const guid = getPlayerGUID();',
|
|
'return readGUID(o.LOCKED_TARGET_GUID);',
|
|
):
|
|
if required not in wow:
|
|
raise SystemExit(f"Missing direct player/target GUID path: {required}")
|
|
for required in (
|
|
'FN_GET_PLAYER_GUID: usize = 0x00468550',
|
|
'LOCKED_TARGET_GUID: usize = 0x00B4E2D8',
|
|
'FN_GET_OBJECT_BY_GUID: usize = 0x464870',
|
|
):
|
|
if required not in offsets:
|
|
raise SystemExit(f"Missing verified WoW offset: {required}")
|
|
print("source: player GUID, target GUID and GUID->object path verified")
|
|
PY
|
|
|
|
- name: Stage package
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
mkdir -p package/DLL
|
|
mkdir -p package/Interface/AddOns/WeirdUtils_Outline
|
|
|
|
cp zig-out/variants/outline.dll package/DLL/
|
|
cp zig-out/variants/customassets.dll package/DLL/
|
|
cp zig-out/variants/transmogfix.dll package/DLL/
|
|
|
|
cp src/outline/addon/Outline.lua package/Interface/AddOns/WeirdUtils_Outline/
|
|
cp src/outline/addon/Bindings.xml package/Interface/AddOns/WeirdUtils_Outline/
|
|
cp src/outline/addon/WeirdUtils_Outline.toc package/Interface/AddOns/WeirdUtils_Outline/
|
|
|
|
cat > package/README_TEST.txt <<'EOF'
|
|
WeirdUtils Safe Standalone Core Test V8 DEBUG
|
|
|
|
DEBUG16 keeps the late D3D9 rehook and reports exact shader/render-target creation stages before draw caching.
|
|
|
|
outline.dll
|
|
- Adds OutlineDebug() sticky in-game diagnostics for the render pipeline.
|
|
- Keeps only the Player_LoadScriptFunctions hook required to register OutlineCommand/OutlineDebug.
|
|
- Keeps only the GameEngine_MainInitialize hook required to initialise the renderer.
|
|
- Does not register the shared WeirdUtils version table.
|
|
- Does not install generic MPQ/file hooks.
|
|
- Uses the external WeirdUtils_Outline addon included here.
|
|
|
|
customassets.dll
|
|
- Keeps only CheckFileExistence from the shared file core.
|
|
- No shared Lua registration hooks.
|
|
- No shared engine/logout/shutdown hooks.
|
|
- Repairs legacy File_FindInArchive NOPs if present.
|
|
|
|
transmogfix.dll
|
|
- Installs only TransmogFix's own module hooks.
|
|
- No shared Lua/file/engine/logout/shutdown hooks.
|
|
|
|
weirdperformance.dll
|
|
- Not built here.
|
|
- The final ZIP will use the user's original binary unchanged.
|
|
EOF
|
|
|
|
sha256sum package/DLL/*.dll > package/SHA256SUMS.txt
|
|
|
|
- uses: actions/upload-artifact@v4
|
|
with:
|
|
name: safe-core-v8-debug
|
|
path: package/
|
|
if-no-files-found: error
|