diff --git a/src/addons.zig b/src/addons.zig index 808f1b5..d564a44 100644 --- a/src/addons.zig +++ b/src/addons.zig @@ -16,8 +16,6 @@ const hook = @import("zhook"); const con = @import("console.zig"); const build_options = @import("build_options"); -const fc: std.builtin.CallingConvention = .{ .x86_fastcall = .{} }; -const sc: std.builtin.CallingConvention = .{ .x86_stdcall = .{} }; // Build option convenience aliases const build_opts = struct { @@ -300,9 +298,9 @@ pub fn findEmbeddedFile(path: [*:0]const u8) ?*const FileEntry { // DLL-embedded addon to register them in the game's addon hash table. // ============================================================================= -var setup_addons_hook: hook.Detour(fn (u32) callconv(fc) void) = .{}; +var setup_addons_hook: hook.Detour(fn (u32) callconv(hook.cc.fastcall) void) = .{}; -fn setupAddonsDetour(mgr_ptr: u32) callconv(fc) void { +fn setupAddonsDetour(mgr_ptr: u32) callconv(hook.cc.fastcall) void { setup_addons_hook.callOriginal(.{mgr_ptr}); inline for (embed_modules) |mod| { @@ -343,7 +341,7 @@ fn hideAddonFromList(name: [*:0]const u8) void { } fn callLoadAddonTOC(addon_name: [*:0]const u8) void { - hook.call(fn ([*:0]const u8) callconv(fc) void, 0x0051c9b0, .{addon_name}); + hook.call(fn ([*:0]const u8) callconv(hook.cc.fastcall) void, 0x0051c9b0, .{addon_name}); } // ============================================================================= diff --git a/src/bigcursor/bigcursor.zig b/src/bigcursor/bigcursor.zig index 17f7b3f..ea38747 100644 --- a/src/bigcursor/bigcursor.zig +++ b/src/bigcursor/bigcursor.zig @@ -13,9 +13,6 @@ const con = @import("../console.zig"); const mod_mutex = @import("../mutex.zig"); const WINAPI = std.builtin.CallingConvention.winapi; -const sc: std.builtin.CallingConvention = .{ .x86_stdcall = .{} }; -const fc: std.builtin.CallingConvention = .{ .x86_fastcall = .{} }; -const tc: std.builtin.CallingConvention = .{ .x86_thiscall = .{} }; pub const module_name: [*:0]const u8 = "bigcursor"; @@ -172,21 +169,19 @@ const IconInfo = extern struct { const CVAR_LOOKUP: usize = 0x0063DEC0; // RegisterCVar: __fastcall(ECX=name, EDX=help, stack: unk1, default, callback, category, unk2, unk3) -const RegisterCVarFn = *const fn ([*:0]const u8, u32, u32, [*:0]const u8, u32, u32, u32, u32) callconv(fc) u32; +const RegisterCVarFn = *const fn ([*:0]const u8, u32, u32, [*:0]const u8, u32, u32, u32, u32) callconv(hook.cc.fastcall) u32; const registerCVar: RegisterCVarFn = @ptrFromInt(0x0063DB90); const CVAR_NAME = "cursorScale"; /// Read CVar integer value (tenths: 15 = 1.5x). Returns f32 scale. fn readCVarScaleInit() f32 { - const cvar_ptr = hook.fastcall(u32, CVAR_LOOKUP, @intFromPtr(@as([*:0]const u8, CVAR_NAME)), @as(u32, 0)); + const cvar_ptr = hook.call(fn ([*:0]const u8) callconv(hook.cc.fastcall) u32, CVAR_LOOKUP, .{CVAR_NAME}); if (cvar_ptr == 0) return g_scale_f; // CVar struct: integer value at offset +40 bytes (10 pointer-sized fields) const val = hook.readMem(i32, cvar_ptr + 40); - if (val >= 10 and val <= 40) { - return @as(f32, @floatFromInt(val)) / 10.0; - } - return g_scale_f; + const clamped = std.math.clamp(val, 5, 40); + return @as(f32, @floatFromInt(clamped)) / 10.0; } // ============================================================================= @@ -277,17 +272,17 @@ const D3DSURFACE_DESC = extern struct { }; fn surfaceGetDesc(surface: *anyopaque, desc: *D3DSURFACE_DESC) i32 { - const f: *const fn (*anyopaque, *D3DSURFACE_DESC) callconv(sc) i32 = @ptrFromInt(vtbl(surface)[SVT_GetDesc]); + const f: *const fn (*anyopaque, *D3DSURFACE_DESC) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vtbl(surface)[SVT_GetDesc]); return f(surface, desc); } fn surfaceLockRect(surface: *anyopaque, locked: *D3DLOCKED_RECT, rect: ?*anyopaque, flags: u32) i32 { - const f: *const fn (*anyopaque, *D3DLOCKED_RECT, ?*anyopaque, u32) callconv(sc) i32 = @ptrFromInt(vtbl(surface)[SVT_LockRect]); + const f: *const fn (*anyopaque, *D3DLOCKED_RECT, ?*anyopaque, u32) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vtbl(surface)[SVT_LockRect]); return f(surface, locked, rect, flags); } fn surfaceUnlockRect(surface: *anyopaque) i32 { - const f: *const fn (*anyopaque) callconv(sc) i32 = @ptrFromInt(vtbl(surface)[SVT_UnlockRect]); + const f: *const fn (*anyopaque) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vtbl(surface)[SVT_UnlockRect]); return f(surface); } @@ -468,8 +463,8 @@ fn cacheClear() void { // Hook: IDirect3DDevice9::SetCursorProperties (VT slot 10) // ============================================================================= -fn hkSetCursorProperties(device: *anyopaque, x_hotspot: u32, y_hotspot: u32, cursor_surface: *anyopaque) callconv(sc) i32 { - const origFn: *const fn (*anyopaque, u32, u32, *anyopaque) callconv(sc) i32 = +fn hkSetCursorProperties(device: *anyopaque, x_hotspot: u32, y_hotspot: u32, cursor_surface: *anyopaque) callconv(hook.cc.stdcall) i32 { + const origFn: *const fn (*anyopaque, u32, u32, *anyopaque) callconv(hook.cc.stdcall) i32 = @ptrFromInt(orig_set_cursor_props); if (g_scale_f <= 1.0) return origFn(device, x_hotspot, y_hotspot, cursor_surface); @@ -532,8 +527,8 @@ fn hkSetCursorProperties(device: *anyopaque, x_hotspot: u32, y_hotspot: u32, cur // Hook: IDirect3DDevice9::ShowCursor (VT slot 12) // ============================================================================= -fn hkShowCursor(device: *anyopaque, bShow: i32) callconv(sc) i32 { - const origFn: *const fn (*anyopaque, i32) callconv(sc) i32 = +fn hkShowCursor(device: *anyopaque, bShow: i32) callconv(hook.cc.stdcall) i32 { + const origFn: *const fn (*anyopaque, i32) callconv(hook.cc.stdcall) i32 = @ptrFromInt(orig_show_cursor); g_cursor_visible = bShow != 0; @@ -557,19 +552,19 @@ fn hkShowCursor(device: *anyopaque, bShow: i32) callconv(sc) i32 { // ============================================================================= fn luaPushNumber(L_ptr: usize, n: f64) void { - hook.call(fn (usize, f64) callconv(tc) void, 0x6F3810, .{ L_ptr, n }); + hook.call(fn (usize, f64) callconv(hook.cc.thiscall) void, 0x6F3810, .{ L_ptr, n }); } pub fn luaSetCursorScale(L: *anyopaque) callconv(.c) u32 { const L_ptr = @intFromPtr(L); - const nargs = hook.fastcall(i32, 0x6F3070, L_ptr, @as(u32, 0)); // lua_gettop + const nargs = hook.call(fn (usize) callconv(hook.cc.fastcall) i32, 0x6F3070, .{L_ptr}); // lua_gettop if (nargs < 1) return 0; - const val: f32 = @floatCast(hook.fastcall(f64, 0x6F3620, L_ptr, @as(i32, 1))); // lua_tonumber - if (val < 1.0 or val > 4.0) return 0; + const val: f32 = @floatCast(hook.call(fn (usize, i32) callconv(hook.cc.fastcall) f64, 0x6F3620, .{ L_ptr, 1 })); // lua_tonumber + const clamped = std.math.clamp(val, 0.5, 4.0); - if (val != g_scale_f) { - g_scale_f = val; + if (clamped != g_scale_f) { + g_scale_f = clamped; cacheClear(); g_hcursor = null; logFmt("[bigcursor] scale set to {d:.2}\n", .{g_scale_f}); diff --git a/src/framecrash/framecrash.zig b/src/framecrash/framecrash.zig index cd06bea..9ddf8f0 100644 --- a/src/framecrash/framecrash.zig +++ b/src/framecrash/framecrash.zig @@ -24,8 +24,6 @@ const hook = @import("zhook"); const con = @import("../console.zig"); const WINAPI = std.builtin.CallingConvention.winapi; -const tc: std.builtin.CallingConvention = .{ .x86_thiscall = .{} }; -const fc: std.builtin.CallingConvention = .{ .x86_fastcall = .{} }; extern "kernel32" fn IsBadReadPtr(lp: ?*const anyopaque, ucb: usize) callconv(WINAPI) i32; extern "kernel32" fn CreateMutexA(lpMutexAttributes: ?*anyopaque, bInitialOwner: i32, lpName: [*:0]const u8) callconv(WINAPI) ?*anyopaque; @@ -94,7 +92,7 @@ const G_PARENT_FRAME_TYPE_ID: usize = 0x00cf0c10; const CLEANUP_TARGET: usize = 0x767720; -const CleanupFn = fn (u32) callconv(tc) void; +const CleanupFn = fn (u32) callconv(hook.cc.thiscall) void; var cleanup_hook: hook.Detour(CleanupFn) = .{}; // ============================================================================= @@ -111,7 +109,7 @@ var cleanup_hook: hook.Detour(CleanupFn) = .{}; const DESTROY_UI_TARGET: usize = 0x7645a0; -const DestroyUIFn = fn (u32, u32) callconv(tc) u32; +const DestroyUIFn = fn (u32, u32) callconv(hook.cc.thiscall) u32; var destroy_ui_hook: hook.Detour(DestroyUIFn) = .{}; // ============================================================================= @@ -125,7 +123,7 @@ var destroy_ui_hook: hook.Detour(DestroyUIFn) = .{}; const PROCESS_UI_TARGET: usize = 0x772ec0; -const ProcessUIFn = fn (u32, u32) callconv(tc) u32; +const ProcessUIFn = fn (u32, u32) callconv(hook.cc.thiscall) u32; var process_ui_hook: hook.Detour(ProcessUIFn) = .{}; // ============================================================================= @@ -143,7 +141,7 @@ var process_ui_hook: hook.Detour(ProcessUIFn) = .{}; const PAUSE_ANIM_TARGET: usize = 0x767ee0; -const PauseAnimFn = fn (u32, u32, u32) callconv(tc) void; +const PauseAnimFn = fn (u32, u32, u32) callconv(hook.cc.thiscall) void; var pause_anim_hook: hook.Detour(PauseAnimFn) = .{}; // ============================================================================= @@ -162,7 +160,7 @@ var pause_anim_hook: hook.Detour(PauseAnimFn) = .{}; const SET_ANIM_TARGET: usize = 0x767c70; -const SetAnimFn = fn (u32, u32, u32, u32, u32, u32, u32) callconv(tc) void; +const SetAnimFn = fn (u32, u32, u32, u32, u32, u32, u32) callconv(hook.cc.thiscall) void; var set_anim_hook: hook.Detour(SetAnimFn) = .{}; // ============================================================================= @@ -286,7 +284,7 @@ fn fmtStaleInfo(relativeTo: u32) struct { name: []const u8, saw_destroy: bool } /// Detour for cleanup_linked_list_structures. Runs before the original to /// walk the dying frame's dependency list and destroy referencing anchors. -fn cleanupDetour(frame: u32) callconv(tc) void { +fn cleanupDetour(frame: u32) callconv(hook.cc.thiscall) void { recordDestruction(frame); cleanupReverseDependencies(frame); cleanup_hook.callOriginal(.{frame}); @@ -296,7 +294,7 @@ fn cleanupDetour(frame: u32) callconv(tc) void { /// called from cleanupGraphicsResources during UI teardown/reload. The original /// frees frames without walking the dependency list, leaving stale anchors. /// Signature: void* __thiscall destroyUIElement(void* this, byte free_flag) -fn destroyUIDetour(frame: u32, free_flag: u32) callconv(tc) u32 { +fn destroyUIDetour(frame: u32, free_flag: u32) callconv(hook.cc.thiscall) u32 { recordDestruction(frame); if (IsBadReadPtr(@ptrFromInt(frame + 0x24), 4) == 0) { recordDestruction(frame + 0x24); @@ -307,7 +305,7 @@ fn destroyUIDetour(frame: u32, free_flag: u32) callconv(tc) u32 { } /// Detour for ProcessUIUpdateEvent - third destruction path, called via vtable. -fn processUIDetour(frame: u32, free_flag: u32) callconv(tc) u32 { +fn processUIDetour(frame: u32, free_flag: u32) callconv(hook.cc.thiscall) u32 { recordDestruction(frame); if (IsBadReadPtr(@ptrFromInt(frame + 0x24), 4) == 0) { recordDestruction(frame + 0x24); @@ -321,7 +319,7 @@ fn processUIDetour(frame: u32, free_flag: u32) callconv(tc) u32 { /// This tells us whether a stale relativeTo was ever registered through the /// normal dependency tracking system. /// Signature: void __thiscall PauseAnimationGroup(ECX=relativeTo_frame, owner_frame, bitmask) -fn pauseAnimDetour(relativeTo_frame: u32, owner_frame: u32, bitmask: u32) callconv(tc) void { +fn pauseAnimDetour(relativeTo_frame: u32, owner_frame: u32, bitmask: u32) callconv(hook.cc.thiscall) void { // Silently record - queried later by vtable hooks via logRegistrationStatus() recordRegistration(relativeTo_frame, owner_frame, bitmask); @@ -330,7 +328,7 @@ fn pauseAnimDetour(relativeTo_frame: u32, owner_frame: u32, bitmask: u32) callco /// Detour for SetAnimationOrder - validates relativeTo param before anchor creation. /// Float params (xOfs, yOfs) are passed as raw u32 bit patterns on the stack. -fn setAnimOrderDetour(frame: u32, point_enum: u32, relativeTo: u32, rel_point: u32, x_ofs: u32, y_ofs: u32, param_6: u32) callconv(tc) void { +fn setAnimOrderDetour(frame: u32, point_enum: u32, relativeTo: u32, rel_point: u32, x_ofs: u32, y_ofs: u32, param_6: u32) callconv(hook.cc.thiscall) void { var fixed_relativeTo = relativeTo; // Validate relativeTo BEFORE the original creates the anchor. @@ -481,7 +479,7 @@ fn getLiveUIParent() u32 { const type_id = readAligned(G_PARENT_FRAME_TYPE_ID); if (type_id == 0) return 0; - const cframe_base = hook.fastcall(u32, GET_FRAME_FROM_LUA, @intFromPtr(@as([*:0]const u8, "UIParent")), type_id); + const cframe_base = hook.call(fn ([*:0]const u8, u32) callconv(hook.cc.fastcall) u32, GET_FRAME_FROM_LUA, .{ "UIParent", type_id }); if (cframe_base == 0) return 0; // Validate the returned pointer @@ -549,8 +547,8 @@ fn isRelativeToValid(relativeTo: u32) bool { /// Hook for vtable[3] GetRelativeTo. Validates the stored pointer. /// If stale, NULLs anchor+0x0C and returns 0 (safe "no relativeTo" path). -fn getRelativeToHook(this: u32) callconv(tc) u32 { - const orig: *const fn (u32) callconv(tc) u32 = @ptrFromInt(orig_get_relative_to); +fn getRelativeToHook(this: u32) callconv(hook.cc.thiscall) u32 { + const orig: *const fn (u32) callconv(hook.cc.thiscall) u32 = @ptrFromInt(orig_get_relative_to); const result = orig(this); if (result == 0) return 0; @@ -573,14 +571,14 @@ fn getRelativeToHook(this: u32) callconv(tc) u32 { /// Hook for vtable[1] GetWidth. Checks anchor+0x0C before calling original. /// Returns sentinel if relativeTo is NULL or dangling. /// Signature: f32 __thiscall GetWidth(this, u32 param) - callee cleans 1 stack arg. -fn getWidthHook(this: u32, param: u32) callconv(tc) f32 { +fn getWidthHook(this: u32, param: u32) callconv(hook.cc.thiscall) f32 { const relativeTo: u32 = readAligned(this + 0x0C); if (!isRelativeToValid(relativeTo)) { if (relativeTo != 0) { // Try to substitute live UIParent instead of NULLing if (tryFixStaleRelativeTo(this, relativeTo)) { // Fixed - call original with the healed pointer - const orig: *const fn (u32, u32) callconv(tc) f32 = @ptrFromInt(orig_get_width); + const orig: *const fn (u32, u32) callconv(hook.cc.thiscall) f32 = @ptrFromInt(orig_get_width); return orig(this, param); } const field: *align(1) u32 = @ptrFromInt(this + 0x0C); @@ -589,19 +587,19 @@ fn getWidthHook(this: u32, param: u32) callconv(tc) f32 { return @as(*align(1) const f32, @ptrFromInt(SENTINEL_ADDR)).*; } - const orig: *const fn (u32, u32) callconv(tc) f32 = @ptrFromInt(orig_get_width); + const orig: *const fn (u32, u32) callconv(hook.cc.thiscall) f32 = @ptrFromInt(orig_get_width); return orig(this, param); } /// Hook for vtable[2] GetHeight. Same pattern as GetWidth. /// Signature: f32 __thiscall GetHeight(this, u32 param) - callee cleans 1 stack arg. -fn getHeightHook(this: u32, param: u32) callconv(tc) f32 { +fn getHeightHook(this: u32, param: u32) callconv(hook.cc.thiscall) f32 { const relativeTo: u32 = readAligned(this + 0x0C); if (!isRelativeToValid(relativeTo)) { if (relativeTo != 0) { // Try to substitute live UIParent instead of NULLing if (tryFixStaleRelativeTo(this, relativeTo)) { - const orig: *const fn (u32, u32) callconv(tc) f32 = @ptrFromInt(orig_get_height); + const orig: *const fn (u32, u32) callconv(hook.cc.thiscall) f32 = @ptrFromInt(orig_get_height); return orig(this, param); } const field: *align(1) u32 = @ptrFromInt(this + 0x0C); @@ -610,7 +608,7 @@ fn getHeightHook(this: u32, param: u32) callconv(tc) f32 { return @as(*align(1) const f32, @ptrFromInt(SENTINEL_ADDR)).*; } - const orig: *const fn (u32, u32) callconv(tc) f32 = @ptrFromInt(orig_get_height); + const orig: *const fn (u32, u32) callconv(hook.cc.thiscall) f32 = @ptrFromInt(orig_get_height); return orig(this, param); } diff --git a/src/interact/interact.zig b/src/interact/interact.zig index 787cd42..9ab2d8c 100644 --- a/src/interact/interact.zig +++ b/src/interact/interact.zig @@ -55,8 +55,6 @@ const C3Vector = struct { // Calling Conventions // ============================================================================= -const sc: std.builtin.CallingConvention = .{ .x86_stdcall = .{} }; -const tc: std.builtin.CallingConvention = .{ .x86_thiscall = .{} }; // ============================================================================= // Game API @@ -65,7 +63,7 @@ const tc: std.builtin.CallingConvention = .{ .x86_thiscall = .{} }; fn getObjectPointer(guid: u64) u32 { const lo: u32 = @truncate(guid); const hi: u32 = @truncate(guid >> 32); - return hook.call(fn (u32, u32) callconv(sc) u32, Offsets.FUN_GET_OBJECT_POINTER, .{ lo, hi }); + return hook.call(fn (u32, u32) callconv(hook.cc.stdcall) u32, Offsets.FUN_GET_OBJECT_POINTER, .{ lo, hi }); } fn isInWorld() bool { @@ -106,11 +104,11 @@ fn isUnitSkinnable(unit: u32) bool { fn setTarget(guid: u64) void { const lo: u32 = @truncate(guid); const hi: u32 = @truncate(guid >> 32); - hook.call(fn (u32, u32) callconv(sc) void, Offsets.FUN_SET_TARGET, .{ lo, hi }); + hook.call(fn (u32, u32) callconv(hook.cc.stdcall) void, Offsets.FUN_SET_TARGET, .{ lo, hi }); } fn rightClickInteract(pointer: u32, autoloot: i32, fun_ptr: usize) void { - hook.call(fn (u32, i32) callconv(tc) void, fun_ptr, .{ pointer, autoloot }); + hook.call(fn (u32, i32) callconv(hook.cc.thiscall) void, fun_ptr, .{ pointer, autoloot }); } // ============================================================================= @@ -134,15 +132,15 @@ fn isBlacklisted(id: u32) bool { } // ============================================================================= -// Lua helpers (hook.fastcall to avoid broken callconv(fc) codegen) +// Lua helpers // ============================================================================= fn luaIsNumber(L: *anyopaque, idx: i32) bool { - return hook.fastcall(u32, Offsets.LUA_ISNUMBER, @intFromPtr(L), idx) != 0; + return hook.call(fn (usize, i32) callconv(hook.cc.fastcall) u32, Offsets.LUA_ISNUMBER, .{ @intFromPtr(L), idx }) != 0; } fn luaToNumber(L: *anyopaque, idx: i32) f64 { - return hook.fastcall(f64, Offsets.LUA_TONUMBER, @intFromPtr(L), idx); + return hook.call(fn (usize, i32) callconv(hook.cc.fastcall) f64, Offsets.LUA_TONUMBER, .{ @intFromPtr(L), idx }); } fn luaPrintError(L: *anyopaque, msg: [*:0]const u8) void { @@ -364,10 +362,10 @@ pub fn lootAllCorpses(_: *anyopaque) callconv(.c) u32 { // Per-frame hook for processing the loot queue. // ============================================================================= -const SceneEndFn = fn (u32) callconv(tc) void; +const SceneEndFn = fn (u32) callconv(hook.cc.thiscall) void; var scene_end_hook: hook.Detour(SceneEndFn) = .{}; -fn hookSceneEnd(device: u32) callconv(tc) void { +fn hookSceneEnd(device: u32) callconv(hook.cc.thiscall) void { if (loot_active) { processLootQueue(); } diff --git a/src/logsessions/logsessions.zig b/src/logsessions/logsessions.zig index a9c0253..046dd4a 100644 --- a/src/logsessions/logsessions.zig +++ b/src/logsessions/logsessions.zig @@ -17,7 +17,6 @@ const con = @import("../console.zig"); const lua = @import("../lua.zig"); const o = @import("offsets.zig"); -const sc = std.builtin.CallingConvention{ .x86_stdcall = .{} }; const WINAPI = std.builtin.CallingConvention.winapi; // ============================================================================= @@ -334,12 +333,12 @@ fn configureSession(char_span: []const u8, realm_span: []const u8) void { // HandleCharacterSelection hook - set up paths before world loading // ============================================================================= -var enter_world_hook: hook.Detour(fn () callconv(sc) void) = .{}; +var enter_world_hook: hook.Detour(fn () callconv(hook.cc.stdcall) void) = .{}; /// Fires when the player clicks Enter World on the character select screen. /// Character name and realm are available from the select screen data. /// Sets up paths BEFORE the world loading sequence calls InitializeLogBuffer. -fn enterWorldDetour() callconv(sc) void { +fn enterWorldDetour() callconv(hook.cc.stdcall) void { asm volatile ("" ::: .{ .esi = true, .edi = true, .ebx = true }); if (!g_paths_configured) { @@ -373,9 +372,9 @@ fn restorePathPointers() void { // InitializeLogBuffer hook - lazy setup + path redirect // ============================================================================= -var init_log_hook: hook.Detour(fn (u32, u32, u32) callconv(sc) u32) = .{}; +var init_log_hook: hook.Detour(fn (u32, u32, u32) callconv(hook.cc.stdcall) u32) = .{}; -fn initLogDetour(file_path: u32, flags: u32, handle_out: u32) callconv(sc) u32 { +fn initLogDetour(file_path: u32, flags: u32, handle_out: u32) callconv(hook.cc.stdcall) u32 { asm volatile ("" ::: .{ .esi = true, .edi = true, .ebx = true }); const path_ptr: [*:0]const u8 = @ptrFromInt(file_path); @@ -405,9 +404,9 @@ fn initLogDetour(file_path: u32, flags: u32, handle_out: u32) callconv(sc) u32 { // WriteFormattedLogMessage hook - inject session markers on first write per log // ============================================================================= -var write_log_hook: hook.Detour(fn (u32, u32, u32) callconv(sc) void) = .{}; +var write_log_hook: hook.Detour(fn (u32, u32, u32) callconv(hook.cc.stdcall) void) = .{}; -fn writeLogDetour(handle: u32, fmt: u32, va_list: u32) callconv(sc) void { +fn writeLogDetour(handle: u32, fmt: u32, va_list: u32) callconv(hook.cc.stdcall) void { asm volatile ("" ::: .{ .esi = true, .edi = true, .ebx = true }); if (g_session_char_len > 0) { diff --git a/src/lua.zig b/src/lua.zig index 8633f67..a554b97 100644 --- a/src/lua.zig +++ b/src/lua.zig @@ -1,22 +1,22 @@ //! WoW 1.12.1 Lua C API wrappers (all __fastcall, L in ECX) const std = @import("std"); -const fc: std.builtin.CallingConvention = .{ .x86_fastcall = .{} }; +const hook = @import("zhook"); pub const State = *anyopaque; pub fn getContext() State { - const f: *const fn () callconv(fc) State = @ptrFromInt(0x7040D0); + const f: *const fn () callconv(hook.cc.fastcall) State = @ptrFromInt(0x7040D0); return f(); } pub fn gettop(L: State) i32 { - const f: *const fn (State) callconv(fc) i32 = @ptrFromInt(0x6F3070); + const f: *const fn (State) callconv(hook.cc.fastcall) i32 = @ptrFromInt(0x6F3070); return f(L); } pub fn settop(L: State, index: i32) void { - const f: *const fn (State, i32) callconv(fc) void = @ptrFromInt(0x6F3080); + const f: *const fn (State, i32) callconv(hook.cc.fastcall) void = @ptrFromInt(0x6F3080); f(L, index); } @@ -25,42 +25,42 @@ pub fn pop(L: State, n: i32) void { } pub fn pushvalue(L: State, index: i32) void { - const f: *const fn (State, i32) callconv(fc) void = @ptrFromInt(0x6F3350); + const f: *const fn (State, i32) callconv(hook.cc.fastcall) void = @ptrFromInt(0x6F3350); f(L, index); } pub fn remove(L: State, index: i32) void { - const f: *const fn (State, i32) callconv(fc) void = @ptrFromInt(0x6F30D0); + const f: *const fn (State, i32) callconv(hook.cc.fastcall) void = @ptrFromInt(0x6F30D0); f(L, index); } pub fn insert(L: State, index: i32) void { - const f: *const fn (State, i32) callconv(fc) void = @ptrFromInt(0x6F31A0); + const f: *const fn (State, i32) callconv(hook.cc.fastcall) void = @ptrFromInt(0x6F31A0); f(L, index); } pub fn typeOf(L: State, index: i32) i32 { - const f: *const fn (State, i32) callconv(fc) i32 = @ptrFromInt(0x6F3400); + const f: *const fn (State, i32) callconv(hook.cc.fastcall) i32 = @ptrFromInt(0x6F3400); return f(L, index); } pub fn typeName(L: State, tp: i32) [*:0]const u8 { - const f: *const fn (State, i32) callconv(fc) [*:0]const u8 = @ptrFromInt(0x6F3480); + const f: *const fn (State, i32) callconv(hook.cc.fastcall) [*:0]const u8 = @ptrFromInt(0x6F3480); return f(L, tp); } pub fn isnumber(L: State, index: i32) bool { - const f: *const fn (State, i32) callconv(fc) u32 = @ptrFromInt(0x6F34D0); + const f: *const fn (State, i32) callconv(hook.cc.fastcall) u32 = @ptrFromInt(0x6F34D0); return f(L, index) != 0; } pub fn isstring(L: State, index: i32) bool { - const f: *const fn (State, i32) callconv(fc) u32 = @ptrFromInt(0x6F3510); + const f: *const fn (State, i32) callconv(hook.cc.fastcall) u32 = @ptrFromInt(0x6F3510); return f(L, index) != 0; } pub fn pushnil(L: State) void { - const f: *const fn (State) callconv(fc) void = @ptrFromInt(0x6F37F0); + const f: *const fn (State) callconv(hook.cc.fastcall) void = @ptrFromInt(0x6F37F0); f(L); } @@ -72,63 +72,62 @@ pub fn pushnumber(L: State, n: f64) void { } pub fn pushstring(L: State, s: [*:0]const u8) void { - const f: *const fn (State, [*:0]const u8) callconv(fc) void = @ptrFromInt(0x6F3890); + const f: *const fn (State, [*:0]const u8) callconv(hook.cc.fastcall) void = @ptrFromInt(0x6F3890); f(L, s); } pub fn pushboolean(L: State, b: i32) void { - const f: *const fn (State, i32) callconv(fc) void = @ptrFromInt(0x6F39F0); + const f: *const fn (State, i32) callconv(hook.cc.fastcall) void = @ptrFromInt(0x6F39F0); f(L, b); } pub fn pushcclosure(L: State, func: usize, n: i32) void { - const f: *const fn (State, usize, i32) callconv(fc) void = @ptrFromInt(0x6F3920); + const f: *const fn (State, usize, i32) callconv(hook.cc.fastcall) void = @ptrFromInt(0x6F3920); @call(.never_tail, f, .{ L, func, n }); } pub fn tonumber(L: State, index: i32) f64 { - const f: *const fn (State, i32) callconv(fc) f64 = @ptrFromInt(0x6F3620); + const f: *const fn (State, i32) callconv(hook.cc.fastcall) f64 = @ptrFromInt(0x6F3620); return f(L, index); } pub fn tostring(L: State, index: i32) ?[*:0]const u8 { - const f: *const fn (State, i32) callconv(fc) ?[*:0]const u8 = @ptrFromInt(0x6F3690); + const f: *const fn (State, i32) callconv(hook.cc.fastcall) ?[*:0]const u8 = @ptrFromInt(0x6F3690); return f(L, index); } pub fn toboolean(L: State, index: i32) i32 { - const f: *const fn (State, i32) callconv(fc) i32 = @ptrFromInt(0x6F3660); + const f: *const fn (State, i32) callconv(hook.cc.fastcall) i32 = @ptrFromInt(0x6F3660); return f(L, index); } pub fn newtable(L: State) void { - const f: *const fn (State) callconv(fc) void = @ptrFromInt(0x6F3C90); + const f: *const fn (State) callconv(hook.cc.fastcall) void = @ptrFromInt(0x6F3C90); f(L); } pub fn settable(L: State, index: i32) void { - const f: *const fn (State, i32) callconv(fc) void = @ptrFromInt(0x6F3E20); + const f: *const fn (State, i32) callconv(hook.cc.fastcall) void = @ptrFromInt(0x6F3E20); f(L, index); } pub fn gettable(L: State, index: i32) void { - const f: *const fn (State, i32) callconv(fc) void = @ptrFromInt(0x6F3A40); + const f: *const fn (State, i32) callconv(hook.cc.fastcall) void = @ptrFromInt(0x6F3A40); f(L, index); } pub fn next(L: State, index: i32) i32 { - const f: *const fn (State, i32) callconv(fc) i32 = @ptrFromInt(0x6F4450); + const f: *const fn (State, i32) callconv(hook.cc.fastcall) i32 = @ptrFromInt(0x6F4450); return f(L, index); } pub fn pcall(L: State, nargs: i32, nresults: i32, errfunc: i32) i32 { - const f: *const fn (State, i32, i32, i32) callconv(fc) i32 = @ptrFromInt(0x6F41A0); + const f: *const fn (State, i32, i32, i32) callconv(hook.cc.fastcall) i32 = @ptrFromInt(0x6F41A0); return @call(.never_tail, f, .{ L, nargs, nresults, errfunc }); } pub fn luaError(L: State, msg: [*:0]const u8) void { - const hook = @import("zhook"); - hook.call(fn (*anyopaque, [*:0]const u8) callconv(.c) void, 0x6F4940, .{ L, msg }); + hook.call(fn (*anyopaque, [*:0]const u8) callconv(hook.cc.cdecl) void, 0x6F4940, .{ L, msg }); } pub const LuaReg = extern struct { @@ -137,11 +136,11 @@ pub const LuaReg = extern struct { }; pub fn openlib(L: State, libname: ?[*:0]const u8, funcs: [*]const LuaReg, nup: i32) void { - const f: *const fn (State, ?[*:0]const u8, [*]const LuaReg, i32) callconv(fc) void = @ptrFromInt(0x6F4DC0); + const f: *const fn (State, ?[*:0]const u8, [*]const LuaReg, i32) callconv(hook.cc.fastcall) void = @ptrFromInt(0x6F4DC0); @call(.never_tail, f, .{ L, libname, funcs, nup }); } pub fn checknumber(L: State, index: i32) f64 { - const f: *const fn (State, i32) callconv(fc) f64 = @ptrFromInt(0x6F4C80); + const f: *const fn (State, i32) callconv(hook.cc.fastcall) f64 = @ptrFromInt(0x6F4C80); return f(L, index); } diff --git a/src/main.zig b/src/main.zig index a59de36..9ef69ab 100644 --- a/src/main.zig +++ b/src/main.zig @@ -33,16 +33,14 @@ const bigcursor = if (build_opts.bigcursor) @import("bigcursor/bigcursor.zig") e const dpslog = if (build_opts.dpslog) @import("dpslog/dpslog.zig") else struct {}; const WINAPI = std.builtin.CallingConvention.winapi; -const fc: std.builtin.CallingConvention = .{ .x86_fastcall = .{} }; -const sc: std.builtin.CallingConvention = .{ .x86_stdcall = .{} }; // ============================================================================= // Lua Protection Bypass // ============================================================================= -var protection_hook: hook.Detour(fn () callconv(sc) void) = .{}; +var protection_hook: hook.Detour(fn () callconv(hook.cc.stdcall) void) = .{}; -fn luaProtectionDetour() callconv(sc) void {} +fn luaProtectionDetour() callconv(hook.cc.stdcall) void {} // ============================================================================= // Lua C API wrappers (WoW 1.12.1 - all __fastcall, L in ECX) @@ -55,11 +53,11 @@ pub const lua = @import("lua.zig"); // ============================================================================= fn registerFunction(name: [*:0]const u8, func_addr: usize) void { - hook.fastcall(void, 0x704120, @intFromPtr(name), func_addr); + hook.call(fn ([*:0]const u8, usize) callconv(hook.cc.fastcall) void, 0x704120, .{ name, func_addr }); } fn allocateGameBuffer(size: u32) ?[*]u8 { - return hook.call(fn (u32, u32, u32, u32) callconv(sc) ?[*]u8, 0x6462E0, .{ + return hook.call(fn (u32, u32, u32, u32) callconv(hook.cc.stdcall) ?[*]u8, 0x6462E0, .{ size, @intFromPtr(@as([*:0]const u8, "weirdutils")), 0, 0, }); } @@ -122,7 +120,7 @@ const findEmbeddedFile = addons.findEmbeddedFile; // Hook: LoadFileWithTextureResourceFallback (0x648620) // ============================================================================= -const LoadFileFn = fn (u32, [*:0]const u8, *?[*]u8, ?*u32, u32, u32, u32) callconv(sc) u32; +const LoadFileFn = fn (u32, [*:0]const u8, *?[*]u8, ?*u32, u32, u32, u32) callconv(hook.cc.stdcall) u32; var file_hook: hook.Detour(LoadFileFn) = .{}; fn loadFileDetour( @@ -133,7 +131,7 @@ fn loadFileDetour( extra_alloc: u32, flags: u32, async_ptr: u32, -) callconv(sc) u32 { +) callconv(hook.cc.stdcall) u32 { if (findEmbeddedFile(path)) |entry| { const data_len: u32 = @intCast(entry.data.len); const total = data_len + extra_alloc; @@ -165,23 +163,22 @@ fn loadFileDetour( // // Fake context detection: type==0, handle(+0x04)==NULL, embedded_ptr(+0x30)!=0 -const OpenFileFn = fn (u32, [*:0]const u8, u32, *u32) callconv(sc) u32; +const OpenFileFn = fn (u32, [*:0]const u8, u32, *u32) callconv(hook.cc.stdcall) u32; var open_file_hook: hook.Detour(OpenFileFn) = .{}; -const GetFileSizeFn = fn (u32, ?*u32) callconv(sc) u32; +const GetFileSizeFn = fn (u32, ?*u32) callconv(hook.cc.stdcall) u32; var get_file_size_hook: hook.Detour(GetFileSizeFn) = .{}; -const ReadFileFn = fn (u32, [*]u8, u32, ?*u32, u32, u32) callconv(sc) u32; +const ReadFileFn = fn (u32, [*]u8, u32, ?*u32, u32, u32) callconv(hook.cc.stdcall) u32; var read_file_hook: hook.Detour(ReadFileFn) = .{}; -const CleanupFileFn = fn (u32) callconv(sc) void; +const CleanupFileFn = fn (u32) callconv(hook.cc.stdcall) void; var cleanup_file_handle_hook: hook.Detour(CleanupFileFn) = .{}; -const ProcessAsyncFn = fn (u32) callconv(fc) void; +const ProcessAsyncFn = fn (u32) callconv(hook.cc.fastcall) void; var process_async_hook: hook.Detour(ProcessAsyncFn) = .{}; -const tc: std.builtin.CallingConvention = .{ .x86_thiscall = .{} }; -const LoadModelFn = fn (u32, u32, u32) callconv(tc) u32; +const LoadModelFn = fn (u32, u32, u32) callconv(hook.cc.thiscall) u32; var model_load_hook: hook.Detour(LoadModelFn) = .{}; // Windows API imports for async handling @@ -199,17 +196,17 @@ fn isFakeFileContext(ctx_addr: u32) bool { /// Call initializeFileContext (0x647290) - __thiscall(ECX=ctx, type) fn callInitFileContext(ctx: [*]u8, file_type: u32) void { - hook.call(fn (u32, u32) callconv(tc) void, 0x647290, .{ @intFromPtr(ctx), file_type }); + hook.call(fn (u32, u32) callconv(hook.cc.thiscall) void, 0x647290, .{ @intFromPtr(ctx), file_type }); } /// Call cleanupFileContext (0x6472d0) - __thiscall(ECX=ctx) fn callCleanupFileContext(ctx: [*]u8) void { - hook.call(fn (u32) callconv(tc) void, 0x6472d0, .{@intFromPtr(ctx)}); + hook.call(fn (u32) callconv(hook.cc.thiscall) void, 0x6472d0, .{@intFromPtr(ctx)}); } /// Free a buffer via FreeMemory/SMemFree (0x646430) - __stdcall(ptr, src, flags) fn freeGameBuffer(ptr: [*]u8) void { - hook.call(fn (u32, u32, u32) callconv(sc) void, 0x646430, .{ + hook.call(fn (u32, u32, u32) callconv(hook.cc.stdcall) void, 0x646430, .{ @intFromPtr(ptr), @intFromPtr(@as([*:0]const u8, "weirdutils")), 0xffffffff, }); } @@ -221,7 +218,7 @@ fn openFileDetour( path: [*:0]const u8, flags: u32, handle_out: *u32, -) callconv(sc) u32 { +) callconv(hook.cc.stdcall) u32 { if (findEmbeddedFile(path)) |entry| { // Allocate and zero-fill 0x60-byte file context const ctx = allocateGameBuffer(0x60) orelse { @@ -259,7 +256,7 @@ fn openFileDetour( fn getFileSizeDetour( file_ctx: u32, high_size_out: ?*u32, -) callconv(sc) u32 { +) callconv(hook.cc.stdcall) u32 { if (isFakeFileContext(file_ctx)) { if (high_size_out) |h| h.* = 0; const size = hook.readMem(u32, file_ctx + 0x34); @@ -279,7 +276,7 @@ fn readFileDetour( bytes_read_out: ?*u32, async_ptr: u32, param6: u32, -) callconv(sc) u32 { +) callconv(hook.cc.stdcall) u32 { if (isFakeFileContext(ctx)) { const data_ptr = hook.readMem(u32, ctx + 0x30); const data_size = hook.readMem(u32, ctx + 0x34); @@ -308,7 +305,7 @@ fn readFileDetour( // --- Hook 4: processAsyncFileOperation (0x647350) --- -fn processAsyncDetour(param1: u32) callconv(fc) void { +fn processAsyncDetour(param1: u32) callconv(hook.cc.fastcall) void { const ctx_addr = hook.readMem(u32, param1 + 0x08); if (isFakeFileContext(ctx_addr)) { @@ -360,7 +357,7 @@ fn processAsyncDetour(param1: u32) callconv(fc) void { // --- Hook 6: CleanupFileHandleResources (0x648730) --- -fn cleanupFileHandleDetour(file_ctx: u32) callconv(sc) void { +fn cleanupFileHandleDetour(file_ctx: u32) callconv(hook.cc.stdcall) void { const fake = isFakeFileContext(file_ctx); if (fake) { const path_ptr = hook.readMem(u32, file_ctx + 0x0C); @@ -381,7 +378,7 @@ fn cleanupFileHandleDetour(file_ctx: u32) callconv(sc) void { // --- Hook 5: loadModelFromFileAsync (0x71d4e0) --- -fn loadModelAsyncDetour(model: u32, file_handle: u32, should_use_callback: u32) callconv(tc) u32 { +fn loadModelAsyncDetour(model: u32, file_handle: u32, should_use_callback: u32) callconv(hook.cc.thiscall) u32 { // file_handle IS the file context address directly (Ghidra shows pointer* but // the assembly pushes it directly to GetFileSizeFromHandle - no dereference) @@ -404,7 +401,7 @@ fn loadModelAsyncDetour(model: u32, file_handle: u32, should_use_callback: u32) // Allocate buffer via setCullMode (0x71f9a0) - same as original path // setCullMode is __fastcall(ECX=size), returns buffer pointer - const buffer_addr = hook.fastcall(u32, 0x71f9a0, data_size, 0); + const buffer_addr = hook.call(fn (u32) callconv(hook.cc.fastcall) u32, 0x71f9a0, .{data_size}); if (buffer_addr == 0) { con.print("[file] setCullMode alloc failed\n"); return 0; @@ -445,7 +442,7 @@ fn loadModelAsyncDetour(model: u32, file_handle: u32, should_use_callback: u32) // Call processLoadedModelData directly - __fastcall(ECX=model) con.fmt("[file] calling processLoadedModelData(0x{x})...\n", .{model}); - const result = hook.fastcall(u32, 0x71d640, model, 0); + const result = hook.call(fn (u32) callconv(hook.cc.fastcall) u32, 0x71d640, .{model}); con.print("[file] processLoadedModelData returned\n"); con.fmt("[file] result=0x{x}\n", .{result}); @@ -473,10 +470,10 @@ fn loadModelAsyncDetour(model: u32, file_handle: u32, should_use_callback: u32) // files are invisible to preloadFileWithFlags, so LoadAddonRecursive skips // Bindings.xml (and SavedVariables) for our addons. -const CheckFileExistenceFn = fn (u32, u32, u32) callconv(fc) u32; +const CheckFileExistenceFn = fn (u32, u32, u32) callconv(hook.cc.fastcall) u32; var cfe_hook: hook.Detour(CheckFileExistenceFn) = .{}; -fn checkFileExistenceDetour(filename_ptr: u32, flags: u32, output_buffer_ptr: u32) callconv(fc) u32 { +fn checkFileExistenceDetour(filename_ptr: u32, flags: u32, output_buffer_ptr: u32) callconv(hook.cc.fastcall) u32 { if (filename_ptr != 0) { // Embedded DLL files const path: [*:0]const u8 = @ptrFromInt(filename_ptr); @@ -516,9 +513,9 @@ fn removeFileHooks() void { // Hook: LoadScriptFunctions (0x490250) // ============================================================================= -var lsf_hook: hook.Detour(fn () callconv(sc) void) = .{}; +var lsf_hook: hook.Detour(fn () callconv(hook.cc.stdcall) void) = .{}; -fn loadScriptFunctionsDetour() callconv(sc) void { +fn loadScriptFunctionsDetour() callconv(hook.cc.stdcall) void { lsf_hook.callOriginal(.{}); registerLuaFunctions(); } @@ -528,9 +525,9 @@ fn loadScriptFunctionsDetour() callconv(sc) void { // Hook: GameEngine_MainInitialize (0x46a400) // ============================================================================= -var engine_init_hook: hook.Detour(fn () callconv(sc) void) = .{}; +var engine_init_hook: hook.Detour(fn () callconv(hook.cc.stdcall) void) = .{}; -fn engineInitDetour() callconv(sc) void { +fn engineInitDetour() callconv(hook.cc.stdcall) void { engine_init_hook.callOriginal(.{}); if (build_opts.screenshot) { @@ -552,9 +549,9 @@ fn engineInitDetour() callconv(sc) void { // Fires on real character logout/disconnect only - NOT on /reload or map change. // ============================================================================= -var logout_hook: hook.Detour(fn () callconv(sc) void) = .{}; +var logout_hook: hook.Detour(fn () callconv(hook.cc.stdcall) void) = .{}; -fn logoutDetour() callconv(sc) void { +fn logoutDetour() callconv(hook.cc.stdcall) void { con.print("[weirdutils] World_HandleLogoutCleanup -- player logout\n"); // Reset per-session state - only on real logout/disconnect, not /reload. @@ -580,7 +577,7 @@ fn logoutDetour() callconv(sc) void { // Hook: CGGameUI_Shutdown (0x490BD0) // ============================================================================= -var shutdown_hook: hook.Detour(fn () callconv(sc) void) = .{}; +var shutdown_hook: hook.Detour(fn () callconv(hook.cc.stdcall) void) = .{}; // ============================================================================= // Module lifecycle - single table drives install, shutdown, and uninstall. @@ -615,7 +612,7 @@ const modules = [_]ModuleHooks{ if (build_opts.screenshot) .{ .name = screenshot.module_name, .remove = screenshot.removeHook, .is_active = screenshot.isActive } else .{}, }; -fn shutdownDetour() callconv(sc) void { +fn shutdownDetour() callconv(hook.cc.stdcall) void { con.print("[weirdutils] CGGameUI_Shutdown\n"); // Per-session resets and remove_on_shutdown cleanup live in logoutDetour // (World_HandleLogoutCleanup) - fires on real logout/disconnect only, not /reload. diff --git a/src/markers/markers.zig b/src/markers/markers.zig index fe5e797..99e31f9 100644 --- a/src/markers/markers.zig +++ b/src/markers/markers.zig @@ -114,9 +114,7 @@ const DespawningEntity = struct { }; var despawning: [MAX_DESPAWNING]?DespawningEntity = .{null} ** MAX_DESPAWNING; -const fc = std.builtin.CallingConvention{ .x86_fastcall = .{} }; -const sc = std.builtin.CallingConvention{ .x86_stdcall = .{} }; -const tc = std.builtin.CallingConvention{ .x86_thiscall = .{} }; + // ============================================================================= // Permission check - leader or raid officer required @@ -125,7 +123,7 @@ const tc = std.builtin.CallingConvention{ .x86_thiscall = .{} }; /// Get local player GUID via GetPlayerGUID (0x468550). /// __fastcall(), no params, returns u64 via EDX:EAX. fn getPlayerGUID() u64 { - return hook.call(fn () callconv(fc) u64, o.FN_GET_PLAYER_GUID, .{}); + return hook.call(fn () callconv(hook.cc.fastcall) u64, o.FN_GET_PLAYER_GUID, .{}); } /// Look up a player name from the name cache by GUID. @@ -133,7 +131,7 @@ fn getPlayerGUID() u64 { fn getNameFromGUID(guid_lo: u32, guid_hi: u32) ?[*:0]const u8 { if (guid_lo == 0 and guid_hi == 0) return null; var name_buf: [2]u32 = .{ 0, 0 }; - const result = hook.call(fn (u32, u32, u32, u32, u32, u32, u32) callconv(tc) u32, o.FN_NAME_CACHE_LOOKUP, .{ + const result = hook.call(fn (u32, u32, u32, u32, u32, u32, u32) callconv(hook.cc.thiscall) u32, o.FN_NAME_CACHE_LOOKUP, .{ o.NAME_CACHE_OBJ, guid_lo, guid_hi, @intFromPtr(&name_buf), 0, 0, 0, }); return if (result != 0) @ptrFromInt(result) else null; @@ -247,7 +245,7 @@ fn getCursorTerrainPosition() ?Vec3 { @as(*align(1) u32, @ptrFromInt(world_frame + o.WF_HIT_TERRAIN_Z)).* = 0; // UpdateHitTest - __fastcall(ECX=worldFrame) - hook.fastcall(void, o.FN_UPDATE_HIT_TEST, world_frame, 0); + hook.call(fn (u32) callconv(hook.cc.fastcall) void, o.FN_UPDATE_HIT_TEST, .{world_frame}); const hit_type = hook.readMem(u32, world_frame + o.WF_HIT_TYPE); const x = hook.readMem(f32, world_frame + o.WF_HIT_TERRAIN_X); @@ -286,7 +284,7 @@ fn getCursorTerrainPosition() ?Vec3 { /// CreateEntityInstance_WithAttachment - __fastcall, RET 0x14. fn createEntityInstance(path: [*:0]const u8, pos: *[3]f32, facing: f32, flags: u32, update_now: u32) ?*anyopaque { - const result = hook.call(fn ([*:0]const u8, *[3]f32, f32, u32, u32, u32, u32) callconv(fc) u32, o.FN_CREATE_ENTITY_INSTANCE, .{ + const result = hook.call(fn ([*:0]const u8, *[3]f32, f32, u32, u32, u32, u32) callconv(hook.cc.fastcall) u32, o.FN_CREATE_ENTITY_INSTANCE, .{ path, pos, facing, flags, update_now, 0, 0, }); return if (result != 0) @ptrFromInt(result) else null; @@ -294,7 +292,7 @@ fn createEntityInstance(path: [*:0]const u8, pos: *[3]f32, facing: f32, flags: u /// CleanupEntity_ProcessAttachments - __fastcall(ECX=entity), no stack params. fn cleanupEntity(obj: *anyopaque) void { - hook.call(fn (*anyopaque) callconv(fc) void, o.FN_CLEANUP_ENTITY, .{obj}); + hook.call(fn (*anyopaque) callconv(hook.cc.fastcall) void, o.FN_CLEANUP_ENTITY, .{obj}); } // ============================================================================= @@ -308,7 +306,7 @@ fn playAnimation(entity: *anyopaque, anim_id: u32, queue: bool) void { const model = hook.readMem(u32, entity_addr + 0x88); if (model == 0 or model < 0x10000) return; - hook.call(fn (u32, u32, u32, i32, u32, u32, u32, u32) callconv(tc) void, o.FN_PLAY_BONE_ANIMATION, .{ + hook.call(fn (u32, u32, u32, i32, u32, u32, u32, u32) callconv(hook.cc.thiscall) void, o.FN_PLAY_BONE_ANIMATION, .{ model, 0xFFFFFFFF, anim_id, -1, 0, @as(u32, @bitCast(@as(f32, 1.0))), 1, @intFromBool(queue), }); } @@ -405,7 +403,7 @@ fn spawnEntity(index: usize, pos: Vec3) bool { /// SetUnitPositionAndOrientation - __fastcall(ECX=positionData, EDX=pos), 1 stack param. fn setUnitPositionAndOrientation(entity: *anyopaque, pos: *[3]f32, facing: f32) void { - hook.call(fn (*anyopaque, *[3]f32, f32) callconv(fc) void, 0x698e20, .{ entity, pos, facing }); + hook.call(fn (*anyopaque, *[3]f32, f32) callconv(hook.cc.fastcall) void, 0x698e20, .{ entity, pos, facing }); } /// Remove only the live entity for a marker slot (def untouched). @@ -517,7 +515,7 @@ pub fn luaClearWorldMarker(L: lua.State) callconv(.c) u32 { } const nargs = lua.gettop(L); - const lua_type: *const fn (lua.State, i32) callconv(fc) i32 = @ptrFromInt(0x6F3400); + const lua_type: *const fn (lua.State, i32) callconv(hook.cc.fastcall) i32 = @ptrFromInt(0x6F3400); if (nargs == 0 or lua_type(L, 1) == 0) { // No args or nil - clear all @@ -729,12 +727,12 @@ pub fn luaCanSetMarkers(L: lua.State) callconv(.c) u32 { // World teardown hook // ============================================================================= -var world_cleanup_hook: hook.Detour(fn () callconv(sc) void) = .{}; -var world_update_hook: hook.Detour(fn (u32) callconv(fc) void) = .{}; +var world_cleanup_hook: hook.Detour(fn () callconv(hook.cc.stdcall) void) = .{}; +var world_update_hook: hook.Detour(fn (u32) callconv(hook.cc.fastcall) void) = .{}; /// OnWorldUpdate hook - per-frame tick while world is active. /// Drives animation state (Hold queue after Stand, despawn cleanup). -fn worldUpdateDetour(frame: u32) callconv(fc) void { +fn worldUpdateDetour(frame: u32) callconv(hook.cc.fastcall) void { tickAnimations(); world_update_hook.callOriginal(.{frame}); } @@ -744,7 +742,7 @@ fn worldUpdateDetour(frame: u32) callconv(fc) void { /// game's teardown runs - the same pattern every native caller uses (e.g. /// processCinematicExit, DestroyPathObjectIfPresent). This unlinks them from /// the WDOODADDEF hash table so the atexit handler never touches freed memory. -fn worldCleanupDetour() callconv(sc) void { +fn worldCleanupDetour() callconv(hook.cc.stdcall) void { con.print("[worldmarkers] >>> worldCleanupDetour FIRING <<<\n"); destroyAllEntities(); world_cleanup_hook.callOriginal(.{}); diff --git a/src/minimapicons/minimapicons.zig b/src/minimapicons/minimapicons.zig index 00d2f4e..f634895 100644 --- a/src/minimapicons/minimapicons.zig +++ b/src/minimapicons/minimapicons.zig @@ -19,9 +19,6 @@ const lua = @import("../lua.zig"); const con = @import("../console.zig"); const mod_mutex = @import("../mutex.zig"); -const fc: std.builtin.CallingConvention = .{ .x86_fastcall = .{} }; -const tc: std.builtin.CallingConvention = .{ .x86_thiscall = .{} }; -const sc: std.builtin.CallingConvention = .{ .x86_stdcall = .{} }; pub const module_name: [*:0]const u8 = "minimapicons"; @@ -248,7 +245,7 @@ const CStatus = extern struct { } fn deinit(self: *CStatus) void { - const f: *const fn (*CStatus) callconv(tc) void = @ptrFromInt(ADDR.CStatusDestructor); + const f: *const fn (*CStatus) callconv(hook.cc.thiscall) void = @ptrFromInt(ADDR.CStatusDestructor); f(self); } }; @@ -365,7 +362,7 @@ fn isValidPtr(addr: u32) bool { fn getObjectByGUID(guid_lo: u32, guid_hi: u32) u32 { if (guid_lo == 0 and guid_hi == 0) return 0; - return hook.call(fn (u32, u32) callconv(sc) u32, ADDR.GetObjectByGUID, .{ guid_lo, guid_hi }); + return hook.call(fn (u32, u32) callconv(hook.cc.stdcall) u32, ADDR.GetObjectByGUID, .{ guid_lo, guid_hi }); } fn getObjectType(obj: u32) u32 { @@ -461,7 +458,7 @@ fn getSummonedByGUID(obj: u32) u64 { } fn getActivePlayerGUID() u64 { - return hook.call(fn () callconv(fc) u64, ADDR.ClntObjMgrGetActivePlayer, .{}); + return hook.call(fn () callconv(hook.cc.fastcall) u64, ADDR.ClntObjMgrGetActivePlayer, .{}); } fn getActivePlayerObject() u32 { @@ -473,7 +470,7 @@ fn getActivePlayerObject() u32 { /// UnitReaction: __thiscall(localPlayer_ECX, unit_stack) -> int (>=4 = friendly). fn unitReaction(local_player: u32, unit: u32) i32 { if (local_player == 0 or unit == 0) return 0; - return hook.call(fn (u32, u32) callconv(tc) i32, ADDR.UnitReaction, .{ local_player, unit }); + return hook.call(fn (u32, u32) callconv(hook.cc.thiscall) i32, ADDR.UnitReaction, .{ local_player, unit }); } /// Check if a unit passes faction/friendliness filters. @@ -514,7 +511,7 @@ fn isUnitAllowed(obj: u32, local_player: u32) bool { /// CallSpellCastHandler: __fastcall(obj_ECX) -> char (bool via virtual dispatch). /// This is what IsValidInteractionTarget uses for type 0x21 (GO). fn isGoInteractable(obj: u32) bool { - const result: u8 = @truncate(hook.call(fn (u32) callconv(fc) u32, ADDR.CallSpellCastHandler, .{obj})); + const result: u8 = @truncate(hook.call(fn (u32) callconv(hook.cc.fastcall) u32, ADDR.CallSpellCastHandler, .{obj})); if (result == 0) { con.fmt("[minimapicons] GO 0x{x} rejected: not interactable (entry={d})\n", .{ obj, getObjectEntry(obj) }); } @@ -549,7 +546,7 @@ fn getObjectPosition(obj: u32) ?C3Vector { if (!isValidPtr(get_pos_fn)) return null; var pos: C3Vector = undefined; // __thiscall(obj_ECX, &pos_stack) → C3Vector* - _ = hook.call(fn (u32, *C3Vector) callconv(tc) u32, get_pos_fn, .{ obj, &pos }); + _ = hook.call(fn (u32, *C3Vector) callconv(hook.cc.thiscall) u32, get_pos_fn, .{ obj, &pos }); return pos; } @@ -569,7 +566,7 @@ fn worldPosToMinimapCoords( // WorldPosToMinimapFrameCoords: __fastcall(out_ECX, edx, C3Vector cur, float radius, // float worldX, float worldY, float layoutScale, float unkScale) // EDX unused — use thiscall (ECX=this, rest on stack) - _ = hook.call(fn (*C2Vector, f32, f32, f32, f32, f32, f32, f32, f32) callconv(tc) u32, ADDR.WorldPosToMinimapCoords, .{ + _ = hook.call(fn (*C2Vector, f32, f32, f32, f32, f32, f32, f32, f32) callconv(hook.cc.thiscall) u32, ADDR.WorldPosToMinimapCoords, .{ out, cur.x, cur.y, cur.z, radius, world_x, world_y, layout_scale, unk_scale, }); } @@ -583,7 +580,7 @@ fn getFrameUnkScale(info: u32) f32 { const fn_addr = hook.readMem(u32, vtable + 7 * 4); if (!isValidPtr(fn_addr)) return 1.0; // __thiscall(fsp_ECX) → f32 on FPU ST(0) - return hook.call(fn (u32) callconv(tc) f32, fn_addr, .{fsp}); + return hook.call(fn (u32) callconv(hook.cc.thiscall) f32, fn_addr, .{fsp}); } // ============================================================================= @@ -621,7 +618,7 @@ fn loadTexture(path: [*:0]const u8) u32 { defer status.deinit(); // TextureCreate: __fastcall(filename_ECX, status_EDX, texFlags, unk1, unk2) - const texture = hook.call(fn ([*:0]const u8, *CStatus, u32, u32, u32) callconv(fc) u32, ADDR.TextureCreate, .{ + const texture = hook.call(fn ([*:0]const u8, *CStatus, u32, u32, u32) callconv(hook.cc.fastcall) u32, ADDR.TextureCreate, .{ path, &status, g_default_tex_flags, 0, 1, }); @@ -642,7 +639,7 @@ fn initTexFlags() u32 { var flags: u32 = 0; // CGxTexFlags constructor: __thiscall(this, filter=0, wrapU=0, wrapV=0, // forceMipTracking=0, generateMipMaps=0, renderTarget=0, maxAnisotropy=0, unknownFlag=1) - hook.call(fn (*u32, u32, u32, u32, u32, u32, u32, u32, u32) callconv(tc) void, ADDR.CGxTexFlagsInit, .{ + hook.call(fn (*u32, u32, u32, u32, u32, u32, u32, u32, u32) callconv(hook.cc.thiscall) void, ADDR.CGxTexFlagsInit, .{ &flags, 0, 0, 0, 0, 0, 0, 0, 1, }); return flags; @@ -658,7 +655,7 @@ fn getGxTex(texture: u32) u32 { status.init(); defer status.deinit(); - const gx_tex = hook.call(fn (u32, u32, *CStatus) callconv(fc) u32, ADDR.TextureGetGxTex, .{ + const gx_tex = hook.call(fn (u32, u32, *CStatus) callconv(hook.cc.fastcall) u32, ADDR.TextureGetGxTex, .{ texture, 1, &status, }); @@ -683,7 +680,7 @@ fn drawMinimapBlip(pos: C2Vector, scale: f32) void { // GxPrimLockVertexPtrs(count=4, vertices, vertStride=12, normal, 0, color, 0, // null, 0, texCoords, 8, null, 0) - hook.call(fn (u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32) callconv(fc) void, ADDR.GxPrimLockVertexPtrs, .{ + hook.call(fn (u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32) callconv(hook.cc.fastcall) void, ADDR.GxPrimLockVertexPtrs, .{ 4, // count (ECX) @intFromPtr(&vertices), // vertices (EDX) 12, // vertStride @@ -700,7 +697,7 @@ fn drawMinimapBlip(pos: C2Vector, scale: f32) void { }); // GxPrimDrawElements(TriangleStrip=4, count=4, indices) - const drawElements: *const fn (u32, u32, u32) callconv(fc) void = @ptrFromInt(ADDR.GxPrimDrawElements); + const drawElements: *const fn (u32, u32, u32) callconv(hook.cc.fastcall) void = @ptrFromInt(ADDR.GxPrimDrawElements); drawElements(4, 4, ADDR.BlipVertIndices); // GxPrimUnlockVertexPtrs() @@ -901,7 +898,7 @@ fn refreshActiveTrackingCache() void { // ObjectEnumProc: __fastcall(MINIMAPINFO* ECX, unused EDX, u64 guid on stack) // When guid is u64, MSVC fastcall skips EDX and puts the 8 bytes on stack. // In Zig fastcall with 4 u32 params: ECX=info, EDX=_edx, stack=guid_lo,guid_hi → RET 8. -const EnumProcFn = fn (u32, u32, u32, u32) callconv(fc) i32; +const EnumProcFn = fn (u32, u32, u32, u32) callconv(hook.cc.fastcall) i32; var enum_proc_hook: hook.Detour(EnumProcFn) = .{}; fn isInCity() bool { @@ -912,7 +909,7 @@ fn isInCity() bool { return false; } -fn objectEnumProcDetour(info: u32, _edx: u32, guid_lo: u32, guid_hi: u32) callconv(fc) i32 { +fn objectEnumProcDetour(info: u32, _edx: u32, guid_lo: u32, guid_hi: u32) callconv(hook.cc.fastcall) i32 { if (g_has_active_tracking and !(g_city_toggle and isInCity())) { if (checkObject(info, guid_lo, guid_hi)) { return 1; // Skip original — we draw our own icon @@ -923,10 +920,10 @@ fn objectEnumProcDetour(info: u32, _edx: u32, guid_lo: u32, guid_hi: u32) callco // RenderObjectBlips: __thiscall(CGMinimapFrame* ECX, DNInfo* stack) // Hooked via fastcall with explicit EDX placeholder. -const RenderBlipsFn = fn (u32, u32, u32) callconv(fc) void; +const RenderBlipsFn = fn (u32, u32, u32) callconv(hook.cc.fastcall) void; var render_blips_hook: hook.Detour(RenderBlipsFn) = .{}; -fn renderObjectBlipsDetour(thisptr: u32, _edx: u32, dn_info: u32) callconv(fc) void { +fn renderObjectBlipsDetour(thisptr: u32, _edx: u32, dn_info: u32) callconv(hook.cc.fastcall) void { render_blips_hook.callOriginal(.{ thisptr, _edx, dn_info }); const count = g_blip_count; @@ -957,7 +954,7 @@ fn renderObjectBlipsDetour(thisptr: u32, _edx: u32, dn_info: u32) callconv(fc) v continue; } - const gxRsSet: *const fn (u32, u32) callconv(fc) void = @ptrFromInt(ADDR.GxRsSet); + const gxRsSet: *const fn (u32, u32) callconv(hook.cc.fastcall) void = @ptrFromInt(ADDR.GxRsSet); gxRsSet(23, gx_tex); // Draw all blips sharing this texture @@ -968,10 +965,10 @@ fn renderObjectBlipsDetour(thisptr: u32, _edx: u32, dn_info: u32) callconv(fc) v } // ClntObjMgrEnumVisibleObjects: __fastcall(callback ECX, context EDX) -const EnumVisFn = fn (u32, u32) callconv(fc) i32; +const EnumVisFn = fn (u32, u32) callconv(hook.cc.fastcall) i32; var enum_vis_hook: hook.Detour(EnumVisFn) = .{}; -fn enumVisibleObjectsDetour(callback: u32, context: u32) callconv(fc) i32 { +fn enumVisibleObjectsDetour(callback: u32, context: u32) callconv(hook.cc.fastcall) i32 { // Clear tracked blips when the minimap's own callback is about to enumerate if (callback == ADDR.ObjectEnumProc) { g_blip_count = 0; @@ -1007,7 +1004,7 @@ fn luaStringToSlice(L: lua.State, idx: i32) ?[]const u8 { } // SetObjectTypeBlip(typeName [, texturePath [, scale [, includeFilter [, excludeFilter]]]]) -pub fn luaSetObjectTypeBlip(L: lua.State) callconv(fc) i32 { +pub fn luaSetObjectTypeBlip(L: lua.State) callconv(hook.cc.fastcall) i32 { defer refreshActiveTrackingCache(); if (!lua.isstring(L, 1)) { @@ -1130,7 +1127,7 @@ pub fn luaSetObjectTypeBlip(L: lua.State) callconv(fc) i32 { } // SetMinimapCityToggle(enabled) — suppress NPC/GO tracking in capital cities -pub fn luaSetCityToggle(L: lua.State) callconv(fc) i32 { +pub fn luaSetCityToggle(L: lua.State) callconv(hook.cc.fastcall) i32 { g_city_toggle = lua.isnumber(L, 1) and lua.tonumber(L, 1) != 0; return 0; } diff --git a/src/outline/api.zig b/src/outline/api.zig index cb1854f..3ec6bfc 100644 --- a/src/outline/api.zig +++ b/src/outline/api.zig @@ -72,13 +72,13 @@ pub fn isEnabled() bool { /// OutlineCommand("on") → enable outlines /// OutlineCommand("off") → disable outlines pub fn outlineCommand(L: *anyopaque) callconv(.c) u32 { - const nargs = hook.fastcall(i32, 0x6F3070, @intFromPtr(L), @as(u32, 0)); // lua_gettop + const nargs = hook.call(fn (usize) callconv(hook.cc.fastcall) i32, 0x6F3070, .{@intFromPtr(L)}); // lua_gettop if (nargs >= 1) { // Check if first arg is a string - const is_str = hook.fastcall(u32, 0x6F3510, @intFromPtr(L), @as(u32, 1)); // lua_isstring + const is_str = hook.call(fn (usize, u32) callconv(hook.cc.fastcall) u32, 0x6F3510, .{ @intFromPtr(L), 1 }); // lua_isstring if (is_str != 0) { - const str_ptr = hook.fastcall(u32, 0x6F3690, @intFromPtr(L), @as(u32, 1)); // lua_tostring + const str_ptr = hook.call(fn (usize, u32) callconv(hook.cc.fastcall) u32, 0x6F3690, .{ @intFromPtr(L), 1 }); // lua_tostring if (str_ptr != 0) { const s: [*:0]const u8 = @ptrFromInt(str_ptr); const span = @import("std").mem.span(s); @@ -92,7 +92,7 @@ pub fn outlineCommand(L: *anyopaque) callconv(.c) u32 { } // Push current state as boolean - hook.fastcall(void, 0x6F39F0, @intFromPtr(L), @as(u32, if (isEnabled()) 1 else 0)); // lua_pushboolean + hook.call(fn (usize, u32) callconv(hook.cc.fastcall) void, 0x6F39F0, .{ @intFromPtr(L), @as(u32, if (isEnabled()) 1 else 0) }); // lua_pushboolean return 1; } diff --git a/src/outline/d3d9_hook.zig b/src/outline/d3d9_hook.zig index aa3fbcd..b3f8b78 100644 --- a/src/outline/d3d9_hook.zig +++ b/src/outline/d3d9_hook.zig @@ -20,7 +20,6 @@ const tracker = @import("tracker.zig"); const model_hook = @import("model_hook.zig"); const WINAPI = std.builtin.CallingConvention.winapi; -const sc: std.builtin.CallingConvention = .{ .x86_stdcall = .{} }; // ============================================================================= // Windows / D3D9 externs @@ -39,7 +38,7 @@ inline fn vt(obj: *anyopaque) [*]usize { /// Call a COM method that takes only (self) and returns HRESULT. fn comCall0(obj: *anyopaque, idx: usize) i32 { - const f: *const fn (*anyopaque) callconv(sc) i32 = @ptrFromInt(vt(obj)[idx]); + const f: *const fn (*anyopaque) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(obj)[idx]); return f(obj); } @@ -86,7 +85,7 @@ const D3DXAssembleShaderFn = *const fn ( u32, // Flags *?*anyopaque, // ppShader (ID3DXBuffer**) *?*anyopaque, // ppErrorMsgs (ID3DXBuffer**) -) callconv(sc) i32; +) callconv(hook.cc.stdcall) i32; // ============================================================================= // Render target resources @@ -161,108 +160,108 @@ const QuadVertex = extern struct { // ============================================================================= fn deviceSetRS(dev: *anyopaque, state: u32, value: u32) void { - const f: *const fn (*anyopaque, u32, u32) callconv(sc) i32 = @ptrFromInt(vt(dev)[types.VT.SetRenderState]); + const f: *const fn (*anyopaque, u32, u32) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(dev)[types.VT.SetRenderState]); _ = f(dev, state, value); } fn deviceGetRS(dev: *anyopaque, state: u32) u32 { var val: u32 = 0; - const f: *const fn (*anyopaque, u32, *u32) callconv(sc) i32 = @ptrFromInt(vt(dev)[types.VT.GetRenderState]); + const f: *const fn (*anyopaque, u32, *u32) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(dev)[types.VT.GetRenderState]); _ = f(dev, state, &val); return val; } fn deviceSetPtr(dev: *anyopaque, idx: usize, ptr: *anyopaque) void { - const f: *const fn (*anyopaque, *anyopaque) callconv(sc) i32 = @ptrFromInt(vt(dev)[idx]); + const f: *const fn (*anyopaque, *anyopaque) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(dev)[idx]); _ = f(dev, ptr); } fn deviceGetPtr(dev: *anyopaque, idx: usize) ?*anyopaque { var ptr: ?*anyopaque = null; - const f: *const fn (*anyopaque, *?*anyopaque) callconv(sc) i32 = @ptrFromInt(vt(dev)[idx]); + const f: *const fn (*anyopaque, *?*anyopaque) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(dev)[idx]); _ = f(dev, &ptr); return ptr; } /// Set a COM pointer, handling null via optional pointer (ABI-equivalent to passing 0). fn deviceSetPtrOrNull(dev: *anyopaque, idx: usize, ptr: ?*anyopaque) void { - const f: *const fn (*anyopaque, ?*anyopaque) callconv(sc) i32 = @ptrFromInt(vt(dev)[idx]); + const f: *const fn (*anyopaque, ?*anyopaque) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(dev)[idx]); _ = @call(.never_tail, f, .{ dev, ptr }); } fn deviceSetPSConstF(dev: *anyopaque, start: u32, data: *const [4]f32) void { - const f: *const fn (*anyopaque, u32, *const [4]f32, u32) callconv(sc) i32 = + const f: *const fn (*anyopaque, u32, *const [4]f32, u32) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(dev)[types.VT.SetPixelShaderConstantF]); _ = f(dev, start, data, 1); } fn deviceGetPSConstF(dev: *anyopaque, start: u32, data: *[4]f32) void { - const f: *const fn (*anyopaque, u32, *[4]f32, u32) callconv(sc) i32 = + const f: *const fn (*anyopaque, u32, *[4]f32, u32) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(dev)[types.VT.GetPixelShaderConstantF]); _ = f(dev, start, data, 1); } fn deviceGetViewport(dev: *anyopaque, vp_out: *types.D3DVIEWPORT9) void { - const f: *const fn (*anyopaque, *types.D3DVIEWPORT9) callconv(sc) i32 = + const f: *const fn (*anyopaque, *types.D3DVIEWPORT9) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(dev)[types.VT.GetViewport]); _ = f(dev, vp_out); } fn deviceSetRenderTarget(dev: *anyopaque, idx: u32, surf: *anyopaque) void { - const f: *const fn (*anyopaque, u32, *anyopaque) callconv(sc) i32 = + const f: *const fn (*anyopaque, u32, *anyopaque) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(dev)[types.VT.SetRenderTarget]); _ = f(dev, idx, surf); } fn deviceGetRenderTarget(dev: *anyopaque, idx: u32) ?*anyopaque { var surf: ?*anyopaque = null; - const f: *const fn (*anyopaque, u32, *?*anyopaque) callconv(sc) i32 = + const f: *const fn (*anyopaque, u32, *?*anyopaque) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(dev)[types.VT.GetRenderTarget]); _ = f(dev, idx, &surf); return surf; } fn deviceSetTexture(dev: *anyopaque, stage: u32, tex: ?*anyopaque) void { - const f: *const fn (*anyopaque, u32, ?*anyopaque) callconv(sc) i32 = + const f: *const fn (*anyopaque, u32, ?*anyopaque) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(dev)[types.VT.SetTexture]); _ = @call(.never_tail, f, .{ dev, stage, tex }); } fn deviceSetFVF(dev: *anyopaque, fvf: u32) void { - const f: *const fn (*anyopaque, u32) callconv(sc) i32 = + const f: *const fn (*anyopaque, u32) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(dev)[types.VT.SetFVF]); _ = f(dev, fvf); } fn deviceGetSamplerState(dev: *anyopaque, sampler: u32, state_type: u32) u32 { var val: u32 = 0; - const f: *const fn (*anyopaque, u32, u32, *u32) callconv(sc) i32 = + const f: *const fn (*anyopaque, u32, u32, *u32) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(dev)[types.VT.GetSamplerState]); _ = f(dev, sampler, state_type, &val); return val; } fn deviceSetSamplerState(dev: *anyopaque, sampler: u32, state_type: u32, value: u32) void { - const f: *const fn (*anyopaque, u32, u32, u32) callconv(sc) i32 = + const f: *const fn (*anyopaque, u32, u32, u32) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(dev)[types.VT.SetSamplerState]); _ = f(dev, sampler, state_type, value); } fn deviceGetStreamSource(dev: *anyopaque, stream: u32, vb_out: *?*anyopaque, offset_out: *u32, stride_out: *u32) void { - const f: *const fn (*anyopaque, u32, *?*anyopaque, *u32, *u32) callconv(sc) i32 = + const f: *const fn (*anyopaque, u32, *?*anyopaque, *u32, *u32) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(dev)[types.VT.GetStreamSource]); _ = f(dev, stream, vb_out, offset_out, stride_out); } fn deviceSetStreamSource(dev: *anyopaque, stream: u32, vb: ?*anyopaque, offset: u32, stride: u32) void { - const f: *const fn (*anyopaque, u32, ?*anyopaque, u32, u32) callconv(sc) i32 = + const f: *const fn (*anyopaque, u32, ?*anyopaque, u32, u32) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(dev)[types.VT.SetStreamSource]); _ = @call(.never_tail, f, .{ dev, stream, vb, offset, stride }); } fn deviceGetTexture(dev: *anyopaque, stage: u32) ?*anyopaque { var tex: ?*anyopaque = null; - const f: *const fn (*anyopaque, u32, *?*anyopaque) callconv(sc) i32 = + const f: *const fn (*anyopaque, u32, *?*anyopaque) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(dev)[types.VT.GetTexture]); _ = f(dev, stage, &tex); return tex; @@ -270,38 +269,38 @@ fn deviceGetTexture(dev: *anyopaque, stage: u32) ?*anyopaque { fn deviceGetIndices(dev: *anyopaque) ?*anyopaque { var ib: ?*anyopaque = null; - const f: *const fn (*anyopaque, *?*anyopaque) callconv(sc) i32 = + const f: *const fn (*anyopaque, *?*anyopaque) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(dev)[types.VT.GetIndices]); _ = f(dev, &ib); return ib; } fn deviceSetIndices(dev: *anyopaque, ib: ?*anyopaque) void { - const f: *const fn (*anyopaque, ?*anyopaque) callconv(sc) i32 = + const f: *const fn (*anyopaque, ?*anyopaque) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(dev)[types.VT.SetIndices]); _ = @call(.never_tail, f, .{ dev, ib }); } fn deviceGetVSConstF(dev: *anyopaque, start: u32, data: [*][4]f32, count: u32) void { - const f: *const fn (*anyopaque, u32, [*][4]f32, u32) callconv(sc) i32 = + const f: *const fn (*anyopaque, u32, [*][4]f32, u32) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(dev)[types.VT.GetVertexShaderConstantF]); _ = f(dev, start, data, count); } fn deviceSetVSConstF(dev: *anyopaque, start: u32, data: [*]const [4]f32, count: u32) void { - const f: *const fn (*anyopaque, u32, [*]const [4]f32, u32) callconv(sc) i32 = + const f: *const fn (*anyopaque, u32, [*]const [4]f32, u32) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(dev)[types.VT.SetVertexShaderConstantF]); _ = f(dev, start, data, count); } fn deviceDrawPrimitiveUP(dev: *anyopaque, prim_type: u32, prim_count: u32, data: *const anyopaque, stride: u32) void { - const f: *const fn (*anyopaque, u32, u32, *const anyopaque, u32) callconv(sc) i32 = + const f: *const fn (*anyopaque, u32, u32, *const anyopaque, u32) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(dev)[types.VT.DrawPrimitiveUP]); _ = f(dev, prim_type, prim_count, data, stride); } fn deviceCreateTexture(dev: *anyopaque, w: u32, h: u32, levels: u32, usage: u32, fmt: u32, pool: u32, out: *?*anyopaque) i32 { - const f: *const fn (*anyopaque, u32, u32, u32, u32, u32, u32, *?*anyopaque, u32) callconv(sc) i32 = + const f: *const fn (*anyopaque, u32, u32, u32, u32, u32, u32, *?*anyopaque, u32) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(dev)[types.VT.CreateTexture]); return f(dev, w, h, levels, usage, fmt, pool, out, 0); } @@ -310,7 +309,7 @@ fn deviceCreateTexture(dev: *anyopaque, w: u32, h: u32, levels: u32, usage: u32, fn textureGetSurfaceLevel(tex: *anyopaque) ?*anyopaque { // IDirect3DTexture9::GetSurfaceLevel is vtable index 18 var surf: ?*anyopaque = null; - const f: *const fn (*anyopaque, u32, *?*anyopaque) callconv(sc) i32 = + const f: *const fn (*anyopaque, u32, *?*anyopaque) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(tex)[18]); if (f(tex, 0, &surf) < 0) return null; return surf; @@ -318,7 +317,7 @@ fn textureGetSurfaceLevel(tex: *anyopaque) ?*anyopaque { /// Clear the current render target to a colour. fn clearRenderTarget(dev: *anyopaque, color: u32) void { - const f: *const fn (*anyopaque, u32, ?*anyopaque, u32, u32, f32, u32) callconv(sc) i32 = + const f: *const fn (*anyopaque, u32, ?*anyopaque, u32, u32, f32, u32) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(dev)[types.VT.Clear]); _ = f(dev, 0, null, types.D3DCLEAR_TARGET, color, 1.0, 0); } @@ -618,10 +617,10 @@ fn assemblePS(device: *anyopaque, assemble: D3DXAssembleShaderFn, src: [*]const // ID3DXBuffer::GetBufferPointer is vtable[3] const buf_ptr: *anyopaque = @ptrFromInt( - @as(*const fn (*anyopaque) callconv(sc) usize, @ptrFromInt(vt(code.?)[3]))(code.?), + @as(*const fn (*anyopaque) callconv(hook.cc.stdcall) usize, @ptrFromInt(vt(code.?)[3]))(code.?), ); var ps_out: ?*anyopaque = null; - const create: *const fn (*anyopaque, *anyopaque, *?*anyopaque) callconv(sc) i32 = + const create: *const fn (*anyopaque, *anyopaque, *?*anyopaque) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(device)[types.VT.CreatePixelShader]); if (create(device, buf_ptr, &ps_out) < 0) return null; return ps_out; @@ -657,7 +656,7 @@ fn buildFullscreenQuad(w: u32, h: u32) [4]QuadVertex { // EndScene hook // ============================================================================= -fn hkEndScene(device: *anyopaque) callconv(sc) i32 { +fn hkEndScene(device: *anyopaque) callconv(hook.cc.stdcall) i32 { // One-time: check if depth/stencil surface has stencil bits. if (need_force_reset) { need_force_reset = false; @@ -686,7 +685,7 @@ fn hkEndScene(device: *anyopaque) callconv(sc) i32 { frame_has_outlines = false; // Call original EndScene - const f: *const fn (*anyopaque) callconv(sc) i32 = @ptrFromInt(orig_endscene); + const f: *const fn (*anyopaque) callconv(hook.cc.stdcall) i32 = @ptrFromInt(orig_endscene); return f(device); } @@ -694,7 +693,7 @@ fn hkEndScene(device: *anyopaque) callconv(sc) i32 { // Reset hook - force D24S8 depth/stencil format, release resources // ============================================================================= -fn hkReset(device: *anyopaque, pp: *types.D3DPRESENT_PARAMETERS) callconv(sc) i32 { +fn hkReset(device: *anyopaque, pp: *types.D3DPRESENT_PARAMETERS) callconv(hook.cc.stdcall) i32 { if (pp.EnableAutoDepthStencil != 0) { const fmt = pp.AutoDepthStencilFormat; if (fmt != types.D3DFMT_D24S8 and fmt != types.D3DFMT_D24FS8 and @@ -709,7 +708,7 @@ fn hkReset(device: *anyopaque, pp: *types.D3DPRESENT_PARAMETERS) callconv(sc) i3 releaseShaders(); releaseResources(); - const f: *const fn (*anyopaque, *types.D3DPRESENT_PARAMETERS) callconv(sc) i32 = @ptrFromInt(orig_reset); + const f: *const fn (*anyopaque, *types.D3DPRESENT_PARAMETERS) callconv(hook.cc.stdcall) i32 = @ptrFromInt(orig_reset); return f(device, pp); } @@ -732,8 +731,8 @@ fn hkDIP( num_verts: u32, start_idx: u32, prim_count: u32, -) callconv(sc) i32 { - const OrigDIP = *const fn (*anyopaque, u32, i32, u32, u32, u32, u32) callconv(sc) i32; +) callconv(hook.cc.stdcall) i32 { + const OrigDIP = *const fn (*anyopaque, u32, i32, u32, u32, u32, u32) callconv(hook.cc.stdcall) i32; const origFn: OrigDIP = @ptrFromInt(orig_dip); // ---- Cache outline draws for EndScene replay ---- @@ -885,7 +884,7 @@ fn runJfaPipeline(device: *anyopaque) void { // Depth-stencil surface var saved_ds: ?*anyopaque = null; - const getDS: *const fn (*anyopaque, *?*anyopaque) callconv(sc) i32 = + const getDS: *const fn (*anyopaque, *?*anyopaque) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(device)[types.VT.GetDepthStencilSurface]); _ = getDS(device, &saved_ds); @@ -935,7 +934,7 @@ fn runJfaPipeline(device: *anyopaque) void { // ===================================================================== if (cached_draw_count > 0) { - const origFn: *const fn (*anyopaque, u32, i32, u32, u32, u32, u32) callconv(sc) i32 = + const origFn: *const fn (*anyopaque, u32, i32, u32, u32, u32, u32) callconv(hook.cc.stdcall) i32 = @ptrFromInt(orig_dip); deviceSetRenderTarget(device, 0, rt_silhouette_surf.?); @@ -985,7 +984,7 @@ fn runJfaPipeline(device: *anyopaque) void { // Clear stencil marks to avoid affecting next frame's rendering deviceSetRS(device, types.D3DRS.STENCILENABLE, 0); - const clearFn: *const fn (*anyopaque, u32, ?*anyopaque, u32, u32, f32, u32) callconv(sc) i32 = + const clearFn: *const fn (*anyopaque, u32, ?*anyopaque, u32, u32, f32, u32) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(device)[types.VT.Clear]); _ = clearFn(device, 0, null, types.D3DCLEAR_STENCIL, 0, 1.0, 0); } @@ -1177,28 +1176,28 @@ fn hasStencilBits(fmt: u32) bool { fn forceD24S8IfNeeded(device: *anyopaque) void { var pDS: ?*anyopaque = null; - const getDS: *const fn (*anyopaque, *?*anyopaque) callconv(sc) i32 = + const getDS: *const fn (*anyopaque, *?*anyopaque) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(device)[types.VT.GetDepthStencilSurface]); if (getDS(device, &pDS) < 0) return; const ds = pDS orelse return; defer comRelease(ds); var desc: types.D3DSURFACE_DESC = .{}; - const getDesc: *const fn (*anyopaque, *types.D3DSURFACE_DESC) callconv(sc) i32 = + const getDesc: *const fn (*anyopaque, *types.D3DSURFACE_DESC) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(ds)[12]); if (getDesc(ds, &desc) < 0) return; if (hasStencilBits(desc.Format)) return; var pSwap: ?*anyopaque = null; - const getSC: *const fn (*anyopaque, u32, *?*anyopaque) callconv(sc) i32 = + const getSC: *const fn (*anyopaque, u32, *?*anyopaque) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(device)[types.VT.GetSwapChain]); if (getSC(device, 0, &pSwap) < 0) return; const swap = pSwap orelse return; defer comRelease(swap); var pp: types.D3DPRESENT_PARAMETERS = .{}; - const getPP: *const fn (*anyopaque, *types.D3DPRESENT_PARAMETERS) callconv(sc) i32 = + const getPP: *const fn (*anyopaque, *types.D3DPRESENT_PARAMETERS) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(swap)[9]); if (getPP(swap, &pp) < 0) return; @@ -1208,7 +1207,7 @@ fn forceD24S8IfNeeded(device: *anyopaque) void { releaseShaders(); releaseResources(); - const resetFn: *const fn (*anyopaque, *types.D3DPRESENT_PARAMETERS) callconv(sc) i32 = + const resetFn: *const fn (*anyopaque, *types.D3DPRESENT_PARAMETERS) callconv(hook.cc.stdcall) i32 = @ptrFromInt(vt(device)[types.VT.Reset]); _ = resetFn(device, &pp); } diff --git a/src/outline/model_hook.zig b/src/outline/model_hook.zig index 0aa393e..4632ca8 100644 --- a/src/outline/model_hook.zig +++ b/src/outline/model_hook.zig @@ -25,15 +25,14 @@ const wow = @import("wow.zig"); // Calling convention constants // ============================================================================= -const tc: std.builtin.CallingConvention = .{ .x86_thiscall = .{} }; // ============================================================================= // Hook state // ============================================================================= -const RenderDrawFn = fn (u32, u32, u32, u32, u32) callconv(tc) void; -const ManageRenderFn = fn (u32, u32) callconv(tc) void; -const DrawBatchFn = fn (u32) callconv(tc) void; +const RenderDrawFn = fn (u32, u32, u32, u32, u32) callconv(hook.cc.thiscall) void; +const ManageRenderFn = fn (u32, u32) callconv(hook.cc.thiscall) void; +const DrawBatchFn = fn (u32) callconv(hook.cc.thiscall) void; var render_draw_hook: hook.Detour(RenderDrawFn) = .{}; var manage_render_hook: hook.Detour(ManageRenderFn) = .{}; @@ -75,7 +74,7 @@ var reordered_indices: [MAX_REORDER]i32 = undefined; // through other players and gear (since those aren't in depth when stencil // is written). The outline composites on top of everything in EndScene. -fn renderDrawDetour(this: u32, view_matrix: u32, batch_data: u32, batch_indices: u32, batch_count: u32) callconv(tc) void { +fn renderDrawDetour(this: u32, view_matrix: u32, batch_data: u32, batch_indices: u32, batch_count: u32) callconv(hook.cc.thiscall) void { // One-time: install D3D9 hooks now that the game is actively rendering. if (d3d9_deferred_pending) { d3d9_deferred_pending = false; @@ -147,7 +146,7 @@ fn renderDrawDetour(this: u32, view_matrix: u32, batch_data: u32, batch_indices: // __thiscall(model_ECX, addToList_stack) // Native thiscall detour - no thunk needed. -fn manageRenderDetour(model: u32, add_to_list: u32) callconv(tc) void { +fn manageRenderDetour(model: u32, add_to_list: u32) callconv(hook.cc.thiscall) void { // Classify the model when it's being ADDED to the render list if (add_to_list == 1 and model != 0 and tracker.enabled and tracker.hasTargets()) { tracker.classifyModel(model); @@ -165,7 +164,7 @@ fn manageRenderDetour(model: u32, add_to_list: u32) callconv(tc) void { // wrong ret instructions for functions with ≤2 register params. The naked // function bridges fastcall → cdecl and calls the implementation function. -fn drawBatchProjDetour(ctx: u32) callconv(tc) void { +fn drawBatchProjDetour(ctx: u32) callconv(hook.cc.thiscall) void { // Fast path: no tracking enabled or nothing tracked → just call original if (!tracker.enabled or !tracker.hasTargets()) { draw_batch_hook.callOriginal(.{ctx}); diff --git a/src/outline/wow.zig b/src/outline/wow.zig index 67d4473..f72e52a 100644 --- a/src/outline/wow.zig +++ b/src/outline/wow.zig @@ -14,9 +14,6 @@ const types = @import("types.zig"); // ============================================================================= const WINAPI = std.builtin.CallingConvention.winapi; -const fc: std.builtin.CallingConvention = .{ .x86_fastcall = .{} }; -const sc: std.builtin.CallingConvention = .{ .x86_stdcall = .{} }; -const tc: std.builtin.CallingConvention = .{ .x86_thiscall = .{} }; extern "kernel32" fn IsBadReadPtr( lp: ?*const anyopaque, @@ -145,7 +142,7 @@ pub fn resolveModelOwner(model: u32) u32 { /// UnitGUID("player") / UnitGUID("target") → 64-bit GUID. /// __fastcall(unitIdStr_ECX) → EDX:EAX (u64). pub fn unitGUID(unit_id: [*:0]const u8) u64 { - return hook.call(fn ([*:0]const u8) callconv(fc) u64, o.FN_UNIT_GUID, .{unit_id}); + return hook.call(fn ([*:0]const u8) callconv(hook.cc.fastcall) u64, o.FN_UNIT_GUID, .{unit_id}); } /// Resolve a GUID → object pointer via the object manager hash table. @@ -154,7 +151,7 @@ pub fn getObjectByGUID(guid: u64) u32 { if (guid == 0) return 0; const lo: u32 = @truncate(guid); const hi: u32 = @truncate(guid >> 32); - return hook.call(fn (u32, u32) callconv(sc) u32, o.FN_GET_OBJECT_BY_GUID, .{ lo, hi }); + return hook.call(fn (u32, u32) callconv(hook.cc.stdcall) u32, o.FN_GET_OBJECT_BY_GUID, .{ lo, hi }); } /// Get the local player's object pointer. @@ -174,7 +171,7 @@ pub fn getTargetGUID() u64 { /// Reaction >= 4 means friendly. pub fn isUnitFriendly(unit: u32, local_player: u32) bool { if (unit == 0 or local_player == 0) return false; - const reaction = hook.call(fn (u32, u32) callconv(tc) i32, o.FN_UNIT_REACTION, .{ local_player, unit }); + const reaction = hook.call(fn (u32, u32) callconv(hook.cc.thiscall) i32, o.FN_UNIT_REACTION, .{ local_player, unit }); return reaction >= 4; } diff --git a/src/screenshot/screenshot.zig b/src/screenshot/screenshot.zig index c043b05..87276e0 100644 --- a/src/screenshot/screenshot.zig +++ b/src/screenshot/screenshot.zig @@ -53,23 +53,21 @@ const ERROR_ALREADY_EXISTS: u32 = 183; // State // ============================================================================= -const tc: std.builtin.CallingConvention = .{ .x86_thiscall = .{} }; -const fc: std.builtin.CallingConvention = .{ .x86_fastcall = .{} }; // CVar for compression level persistence (0–9, default 6) const CVAR_NAME = "screenshotQuality"; const CVAR_LOOKUP: usize = 0x0063DEC0; -const RegisterCVarFn = *const fn ([*:0]const u8, u32, u32, [*:0]const u8, u32, u32, u32, u32) callconv(fc) u32; +const RegisterCVarFn = *const fn ([*:0]const u8, u32, u32, [*:0]const u8, u32, u32, u32, u32) callconv(hook.cc.fastcall) u32; const registerCVar: RegisterCVarFn = @ptrFromInt(0x0063DB90); fn readCVarQuality() i32 { - const cvar_ptr = hook.fastcall(u32, CVAR_LOOKUP, @intFromPtr(@as([*:0]const u8, CVAR_NAME)), @as(u32, 0)); + const cvar_ptr = hook.call(fn ([*:0]const u8) callconv(hook.cc.fastcall) u32, CVAR_LOOKUP, .{CVAR_NAME}); if (cvar_ptr == 0) return 6; const val = hook.readMem(i32, cvar_ptr + 40); return std.math.clamp(val, 0, 9); } -const TgaWriteFn = fn (u32, u32) callconv(tc) i32; +const TgaWriteFn = fn (u32, u32) callconv(hook.cc.thiscall) i32; var tga_hook: hook.Detour(TgaWriteFn) = .{}; var screenshot_dir: [260]u8 = undefined; var screenshot_dir_len: usize = 0; @@ -153,7 +151,7 @@ fn callOriginal(self: u32, filename: u32) i32 { // Thunked from __fastcall(self_ECX, _EDX, filename_stack) → cdecl // ============================================================================= -fn tgaWriteDetour(self: u32, filename: u32) callconv(tc) i32 { +fn tgaWriteDetour(self: u32, filename: u32) callconv(hook.cc.thiscall) i32 { // CVar 0 = disabled, fall through to original TGA write const quality = readCVarQuality(); if (quality == 0) return callOriginal(self, filename); diff --git a/src/transmogfix/transmogfix.zig b/src/transmogfix/transmogfix.zig index f7027c9..e050219 100644 --- a/src/transmogfix/transmogfix.zig +++ b/src/transmogfix/transmogfix.zig @@ -61,13 +61,13 @@ const DISPLAY_INFO_TABLE_PTR: usize = 0x00c0de90; // ============================================================================= fn unitGUID(unit_id: [*:0]const u8) u64 { - return hook.call(fn ([*:0]const u8) callconv(fc) u64, ADDR_UnitGUID, .{unit_id}); + return hook.call(fn ([*:0]const u8) callconv(hook.cc.fastcall) u64, ADDR_UnitGUID, .{unit_id}); } fn getObjectByGUID(guid: u64) u32 { const lo: u32 = @truncate(guid); const hi: u32 = @truncate(guid >> 32); - return hook.call(fn (u32, u32) callconv(sc) u32, ADDR_GetObjectByGUID, .{ lo, hi }); + return hook.call(fn (u32, u32) callconv(hook.cc.stdcall) u32, ADDR_GetObjectByGUID, .{ lo, hi }); } fn updateInventoryAlertStates() void { @@ -76,11 +76,11 @@ fn updateInventoryAlertStates() void { } fn refreshAppearanceAndEquipment(unit: u32) void { - hook.fastcall(void, ADDR_RefreshAppearance, unit, @as(u32, 0)); + hook.call(fn (u32) callconv(hook.cc.fastcall) void, ADDR_RefreshAppearance, .{unit}); } fn refreshEquipmentDisplay(unit: u32) void { - hook.fastcall(void, ADDR_RefreshEquipmentDisplay, unit, @as(u32, 0)); + hook.call(fn (u32) callconv(hook.cc.fastcall) void, ADDR_RefreshEquipmentDisplay, .{unit}); } // ============================================================================= @@ -153,12 +153,9 @@ pub fn isActive() bool { // Hooks // ============================================================================= -const tc: std.builtin.CallingConvention = .{ .x86_thiscall = .{} }; -const fc: std.builtin.CallingConvention = .{ .x86_fastcall = .{} }; -const sc: std.builtin.CallingConvention = .{ .x86_stdcall = .{} }; -const SetBlockFn = fn (u32, u32, u32) callconv(tc) u32; -const RefreshFn = fn (u32, u32, u32, u32) callconv(tc) void; -const SceneEndFn = fn (u32) callconv(tc) void; +const SetBlockFn = fn (u32, u32, u32) callconv(hook.cc.thiscall) u32; +const RefreshFn = fn (u32, u32, u32, u32) callconv(hook.cc.thiscall) void; +const SceneEndFn = fn (u32) callconv(hook.cc.thiscall) void; var set_block_hook: hook.Detour(SetBlockFn) = .{}; var refresh_hook: hook.Detour(RefreshFn) = .{}; @@ -473,7 +470,7 @@ fn processTimeouts(now: u32) void { // Hook 1: SetBlock (0x6142E0) // ============================================================================= -fn hookSetBlock(obj: u32, index: u32, value: u32) callconv(tc) u32 { +fn hookSetBlock(obj: u32, index: u32, value: u32) callconv(hook.cc.thiscall) u32 { const val = value; // VISIBLE_ITEM writes @@ -648,7 +645,7 @@ fn hookSetBlock(obj: u32, index: u32, value: u32) callconv(tc) u32 { // Hook 2: RefreshVisualAppearance (0x5fb880) // ============================================================================= -fn hookRefreshVisualAppearance(unit: u32, event_data: u32, extra_data: u32, force_update: u32) callconv(tc) void { +fn hookRefreshVisualAppearance(unit: u32, event_data: u32, extra_data: u32, force_update: u32) callconv(hook.cc.thiscall) void { if (!g_enabled or refresh_hook.inner.trampoline == 0) { if (refresh_hook.inner.trampoline != 0) { callOriginalRefresh(unit, event_data, extra_data, force_update); @@ -754,7 +751,7 @@ fn hookRefreshVisualAppearance(unit: u32, event_data: u32, extra_data: u32, forc // Hook 3: SceneEnd (0x5a17a0) // ============================================================================= -fn hookSceneEnd(device: u32) callconv(tc) void { +fn hookSceneEnd(device: u32) callconv(hook.cc.thiscall) void { if (g_enabled and (g_local_pending_count > 0 or g_other_pending_count > 0)) { processTimeouts(GetTickCount()); }