Add module control API, bigcursor with fractional scaling, shared mutex
Module control API: - Three cdecl exports: WeirdUtils_IsModuleActive, WeirdUtils_DisableModule, WeirdUtils_DisableAll - C header include/weirdutils_api.h for runtime DLL discovery - All modules gain pub module_name, isActive(), shared mutex via src/mutex.zig - build.zig refactored to module_list array of ModuleDesc Bigcursor: - D3D9 vtable hooks on SetCursorProperties/ShowCursor - Scale2x/Scale3x pixel-art upscalers in pure Zig (replaces 12K-line hqx C) - Bilinear resampler for fractional scales (1.0-4.0, default 1.2) - Win32 cursor via CreateIconIndirect bypasses D3D9 32x32 limit - FNV-1a hash cache for ~16 cursor bitmaps - Lua API: SetCursorScale(n) / GetCursorScale() - CVar cursorScale for Config.wtf persistence (tenths) Other: - Add dpslog module stub - Docs and README updates
This commit is contained in:
+32
-32
@@ -20,7 +20,7 @@ pub const MOVEMENT_POS_Z: usize = 0x18;
|
||||
// Entity creation (high-level API)
|
||||
// =============================================================================
|
||||
|
||||
/// CreateEntityInstance_WithAttachment — __fastcall, RET 0x14 (5 stack params).
|
||||
/// CreateEntityInstance_WithAttachment - __fastcall, RET 0x14 (5 stack params).
|
||||
/// ECX = modelPath (char*), EDX = position (float[3]*)
|
||||
/// Stack: facing (float), flags (int), updateNow (int), param6 (int), param7 (int)
|
||||
/// Returns: entity pointer (int*).
|
||||
@@ -37,7 +37,7 @@ pub const FN_CREATE_ENTITY_INSTANCE: usize = 0x006707c0;
|
||||
// World teardown (map unload / logout / exit)
|
||||
// =============================================================================
|
||||
|
||||
/// CleanupWorldAndEntities — void(), no params, __stdcall.
|
||||
/// CleanupWorldAndEntities - void(), no params, __stdcall.
|
||||
/// Top-level world teardown: calls CleanupEntityList_ProcessAll, then
|
||||
/// CleanupWorldAndReleaseResources (which iterates heaps and force-frees).
|
||||
/// Called from InitializeWorldScene (map change) and ShutdownClientSystems (exit).
|
||||
@@ -52,21 +52,21 @@ pub const FN_CLEANUP_WORLD_AND_ENTITIES: usize = 0x0066fc40;
|
||||
/// __fastcall returns void**
|
||||
pub const FN_ALLOCATE_WORLD_OBJECT: usize = 0x006a0930;
|
||||
|
||||
/// DestroyWorldObjectAndRelease(object) — __fastcall, ECX=obj, no stack params.
|
||||
/// DestroyWorldObjectAndRelease(object) - __fastcall, ECX=obj, no stack params.
|
||||
/// Unlinks from world object list (+0x10/+0x14), calls virtual destructor, frees heap.
|
||||
/// ONLY for objects on WENTITY heap (from AllocateAndInitializeWorldObject).
|
||||
pub const FN_DESTROY_WORLD_OBJECT: usize = 0x006a0a70;
|
||||
|
||||
/// CleanupEntity_ProcessAttachments(entity) — __fastcall, ECX=entity, no stack params.
|
||||
/// CleanupEntity_ProcessAttachments(entity) - __fastcall, ECX=entity, no stack params.
|
||||
/// High-level destructor counterpart to CreateEntityInstance_WithAttachment.
|
||||
/// Walks and frees attachment children, decrements refcount at +0x0E, then
|
||||
/// dispatches to type-specific destructor based on flags at +0x8:
|
||||
/// flag 0x8 (M2): destroyWorldEnvironment (0x6a6870) — scene graph removal + free
|
||||
/// flag 0x40 (WMO): cleanupGameObject (0x6a67a0) — render detach + spatial unlink + free
|
||||
/// flag 0x8 (M2): destroyWorldEnvironment (0x6a6870) - scene graph removal + free
|
||||
/// flag 0x40 (WMO): cleanupGameObject (0x6a67a0) - render detach + spatial unlink + free
|
||||
/// Only actually frees when refcount reaches 0.
|
||||
pub const FN_CLEANUP_ENTITY: usize = 0x00670d50;
|
||||
|
||||
/// DecrementReferenceCount(obj) — __fastcall, ECX=obj, no stack params.
|
||||
/// DecrementReferenceCount(obj) - __fastcall, ECX=obj, no stack params.
|
||||
/// Decrements ref count; when it reaches 0, calls virtual destructor to free.
|
||||
pub const FN_DECREMENT_REFCOUNT: usize = 0x007103a0;
|
||||
|
||||
@@ -74,10 +74,10 @@ pub const FN_DECREMENT_REFCOUNT: usize = 0x007103a0;
|
||||
// Cursor terrain position
|
||||
// =============================================================================
|
||||
|
||||
/// WorldFrame global pointer — *(u32*)PTR = worldFrame object.
|
||||
/// WorldFrame global pointer - *(u32*)PTR = worldFrame object.
|
||||
pub const PTR_WORLD_FRAME: usize = 0x00B4B2BC;
|
||||
|
||||
/// UpdateHitTest — __fastcall(ECX=worldFrame), no stack params.
|
||||
/// UpdateHitTest - __fastcall(ECX=worldFrame), no stack params.
|
||||
/// Raycasts from camera through mouse cursor, stores result at worldFrame+0x350:
|
||||
/// +0x350: hit type (0=none, 1=terrain, 2=object)
|
||||
/// +0x360: terrain intersection X (f32)
|
||||
@@ -95,7 +95,7 @@ pub const WF_HIT_TERRAIN_Z: usize = 0x368;
|
||||
// Zone / area identification
|
||||
// =============================================================================
|
||||
|
||||
/// Current zone area ID — numeric, locale-safe zone identifier.
|
||||
/// Current zone area ID - numeric, locale-safe zone identifier.
|
||||
/// Updated by the game as the player moves between areas.
|
||||
pub const ZONE_AREA_ID: usize = 0x00B4E314;
|
||||
|
||||
@@ -103,7 +103,7 @@ pub const ZONE_AREA_ID: usize = 0x00B4E314;
|
||||
// Per-frame world update
|
||||
// =============================================================================
|
||||
|
||||
/// OnWorldUpdate — __fastcall(ECX=worldFrame), no stack params, void return.
|
||||
/// OnWorldUpdate - __fastcall(ECX=worldFrame), no stack params, void return.
|
||||
/// Called every frame while the world is active (in-game, not login screen).
|
||||
/// Part of CGWorldFrame update pipeline.
|
||||
pub const FN_ON_WORLD_UPDATE: usize = 0x00482EA0;
|
||||
@@ -123,7 +123,7 @@ pub const FN_CM2_CREATE_FOR_MODEL_OBJECT: usize = 0x00695100;
|
||||
// Animation
|
||||
// =============================================================================
|
||||
|
||||
/// CM2Model__PlayBoneAnimation — __thiscall(ECX=modelRenderCtx), RET 0x1c (7 stack params).
|
||||
/// CM2Model__PlayBoneAnimation - __thiscall(ECX=modelRenderCtx), RET 0x1c (7 stack params).
|
||||
/// (boneIndex, animId, sequenceIndex, animData*, speed, blendMode, queueAnimation)
|
||||
/// boneIndex: 0xFFFFFFFF = all bones
|
||||
/// animId: M2 animation ID (0=Stand, 158=Hold, 159=Decay for Raid_UI_FX)
|
||||
@@ -138,75 +138,75 @@ pub const FN_PLAY_BONE_ANIMATION: usize = 0x007121a0;
|
||||
// Transform and position
|
||||
// =============================================================================
|
||||
|
||||
/// UpdateObjectTransform_CalculateBounds — __fastcall, RET 0x0C
|
||||
/// UpdateObjectTransform_CalculateBounds - __fastcall, RET 0x0C
|
||||
/// ECX = world object, EDX = 4x4 transform matrix (float[16])
|
||||
/// Stack: bounds (float[6] min/max), halfExtents (float[3]), forceUpdate (int)
|
||||
pub const FN_UPDATE_OBJECT_TRANSFORM: usize = 0x006717d0;
|
||||
|
||||
// =============================================================================
|
||||
// File I/O (Storm) — for in-memory file serving
|
||||
// File I/O (Storm) - for in-memory file serving
|
||||
// =============================================================================
|
||||
|
||||
/// openFileWithOptions — __stdcall(4), RET 0x10, prologue=9
|
||||
/// openFileWithOptions - __stdcall(4), RET 0x10, prologue=9
|
||||
/// (archive_ptr, path, flags, handle_out) → type_code (0=fail, 1-4=success)
|
||||
pub const FN_OPEN_FILE_WITH_OPTIONS: usize = 0x006477c0;
|
||||
|
||||
/// GetFileSizeFromHandle — __stdcall(2), RET 0x08, prologue=6
|
||||
/// GetFileSizeFromHandle - __stdcall(2), RET 0x08, prologue=6
|
||||
/// (file_context, high_size_out) → size
|
||||
pub const FN_GET_FILE_SIZE: usize = 0x006487f0;
|
||||
|
||||
/// ReadFileFromMultipleSources — __stdcall(6), RET 0x18, prologue=6
|
||||
/// ReadFileFromMultipleSources - __stdcall(6), RET 0x18, prologue=6
|
||||
/// (context, buffer, size, bytes_read_out, async_ptr, param6) → bool
|
||||
/// async_ptr==NULL: synchronous read. Non-NULL: queues async operation.
|
||||
pub const FN_READ_FILE: usize = 0x00648460;
|
||||
|
||||
/// CleanupFileHandleResources — __stdcall(1), RET 0x04, prologue=7
|
||||
/// CleanupFileHandleResources - __stdcall(1), RET 0x04, prologue=7
|
||||
/// (file_context) → 1
|
||||
pub const FN_CLEANUP_FILE_HANDLE: usize = 0x00648730;
|
||||
|
||||
/// processAsyncFileOperation — __fastcall(ECX=request), plain RET, prologue=7
|
||||
/// processAsyncFileOperation - __fastcall(ECX=request), plain RET, prologue=7
|
||||
/// Request structure: +0x08=file_ctx, +0x0C=dest_buf, +0x10=read_size,
|
||||
/// +0x14=seek/event_struct (*(+0x14)+4 = event handle)
|
||||
pub const FN_PROCESS_ASYNC_FILE_OP: usize = 0x00647350;
|
||||
|
||||
/// initializeFileContext — __thiscall(ECX=ctx, type)
|
||||
/// initializeFileContext - __thiscall(ECX=ctx, type)
|
||||
/// Sets context type, initializes critical section at +0x24, zeroes fields.
|
||||
pub const FN_INIT_FILE_CONTEXT: usize = 0x00647290;
|
||||
|
||||
/// cleanupFileContext — __thiscall(ECX=ctx)
|
||||
/// cleanupFileContext - __thiscall(ECX=ctx)
|
||||
/// Destroys critical section, cleanup companion to initializeFileContext.
|
||||
pub const FN_CLEANUP_FILE_CONTEXT: usize = 0x006472d0;
|
||||
|
||||
/// FreeMemory (SMemFree) — __stdcall(3): (ptr, src_str, flags)
|
||||
/// FreeMemory (SMemFree) - __stdcall(3): (ptr, src_str, flags)
|
||||
pub const FN_FREE_MEMORY: usize = 0x00646430;
|
||||
|
||||
// =============================================================================
|
||||
// M2 model loading (async pipeline)
|
||||
// =============================================================================
|
||||
|
||||
/// loadModelFromFileAsync — __thiscall(ECX=model_obj), 2 stack params, RET 0x08
|
||||
/// loadModelFromFileAsync - __thiscall(ECX=model_obj), 2 stack params, RET 0x08
|
||||
/// (fileHandle: **ctx, shouldUseCallback: int) → 1
|
||||
/// Prologue: 55 8b ec 8b 55 0c 56 8b f1 — safe sizes: [6, 7, 9]
|
||||
/// Prologue: 55 8b ec 8b 55 0c 56 8b f1 - safe sizes: [6, 7, 9]
|
||||
/// Allocates async task to read file and call onModelLoadComplete when done.
|
||||
/// The async executor at 0x71d610 calls fileReadWithLock directly, bypassing
|
||||
/// our ReadFileFromMultipleSources hook — hence this hook fills the buffer
|
||||
/// our ReadFileFromMultipleSources hook - hence this hook fills the buffer
|
||||
/// synchronously for fake file contexts.
|
||||
pub const FN_LOAD_MODEL_ASYNC: usize = 0x0071d4e0;
|
||||
|
||||
/// processLoadedModelData — __fastcall(ECX=model), no stack params, plain RET
|
||||
/// processLoadedModelData - __fastcall(ECX=model), no stack params, plain RET
|
||||
/// Parses model header from buffer at model+0x130 (ptr) / model+0x134 (size),
|
||||
/// initializes model resources, sets bit 0 of model+8 when done.
|
||||
pub const FN_PROCESS_LOADED_MODEL_DATA: usize = 0x0071d640;
|
||||
|
||||
// =============================================================================
|
||||
// Permission check — leader / raid officer
|
||||
// Permission check - leader / raid officer
|
||||
// =============================================================================
|
||||
|
||||
/// Group leader GUID (64-bit): low u32 at +0, high u32 at +4.
|
||||
/// Valid for both party leader and raid leader.
|
||||
pub const LEADER_GUID: usize = 0x00bc75f8;
|
||||
|
||||
/// Raid roster — array of 40 pointers to roster entry structs.
|
||||
/// Raid roster - array of 40 pointers to roster entry structs.
|
||||
/// Entry layout: +0x00/+0x04 = GUID (u64), +0x08 = subgroup, +0x0C = rank.
|
||||
/// Rank: 0 = member, 1 = assistant, 2 = leader.
|
||||
pub const RAID_ROSTER_ARRAY: usize = 0x00b712a8;
|
||||
@@ -217,18 +217,18 @@ pub const RAID_MEMBER_COUNT: usize = 0x00b713e0;
|
||||
/// Offset within a roster entry to the rank field (i32).
|
||||
pub const ROSTER_ENTRY_RANK: usize = 0x0C;
|
||||
|
||||
/// Party member GUIDs — 4 slots, 8 bytes each (lo/hi u32 pairs).
|
||||
/// Party member GUIDs - 4 slots, 8 bytes each (lo/hi u32 pairs).
|
||||
/// Contains other party members (not local player). Stride = 8.
|
||||
pub const PARTY_MEMBER_GUIDS: usize = 0x00bc6f48;
|
||||
|
||||
/// GetPlayerGUID — __fastcall(), no params, returns EAX(low):EDX(high).
|
||||
/// GetPlayerGUID - __fastcall(), no params, returns EAX(low):EDX(high).
|
||||
pub const FN_GET_PLAYER_GUID: usize = 0x00468550;
|
||||
|
||||
/// RetrieveNPCDataFromCache — __thiscall(ECX=cache_obj), 6 stack params, RET 0x18.
|
||||
/// RetrieveNPCDataFromCache - __thiscall(ECX=cache_obj), 6 stack params, RET 0x18.
|
||||
/// (guid_low, guid_high, name_buf_ptr, 0, 0, 0) → char* name or NULL.
|
||||
/// Used by GetRaidRosterInfo to resolve player names from GUIDs.
|
||||
pub const FN_NAME_CACHE_LOOKUP: usize = 0x0055f080;
|
||||
|
||||
/// Name cache object — static instance at this address. Passed as ECX (this)
|
||||
/// Name cache object - static instance at this address. Passed as ECX (this)
|
||||
/// to RetrieveNPCDataFromCache.
|
||||
pub const NAME_CACHE_OBJ: usize = 0x00c0e228;
|
||||
|
||||
Reference in New Issue
Block a user