Publish source: Unlicense, public README, repo hygiene
The remote was previously a distribution-only point for pre-built DLLs. This opens the source. - LICENSE: Unlicense, with a GPL-3.0 carve-out for src/dpslog/WeirdDPSMate (a DPSMate fork that keeps its own license) - README.md replaces the stale internal one with the user-facing docs from DLL_README.md, swapping the 'Why No Source Code?' section for build and layout notes. DLL_README.md is dropped; one README now serves both. - RELEASING.md: drop the trim-the-README-per-release dance and the remote/WeirdUtils/ distribution clone, both obsolete now - gitignore agent/editor scratch, build caches, the vendored WSBT addon, and the WeirdThreat/uwu-logs checkouts (separate upstream repos) - Commit outstanding module work: superweirdo, clickthrough portal visuals, transform44 decompiles, worldmarkers demo presets, tools/
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
# WoW 1.12.1 CPU Profiling Analysis
|
||||
|
||||
Source: `perf.data.perfparser` (July 2025 recording via hotspot)
|
||||
Exported: `cycles.out` (stack-collapsed format)
|
||||
|
||||
## Full CPU Time Breakdown
|
||||
|
||||
| % | Category | Notes |
|
||||
|---|---|---|
|
||||
| 33.18% | **Hooked WoW functions** | 38 hooks in transform44 module |
|
||||
| 19.19% | GPU/Driver | d3d9.dll (DXVK) + amdvlk32.so -- untouchable |
|
||||
| 18.74% | WoW long tail | ~2000+ functions each <0.15% -- not worth hooking |
|
||||
| 13.15% | WoW mid-tier | 50 functions at 0.15-0.39% -- hookable but diminishing returns |
|
||||
| 8.43% | Lua VM | lua_vm_execute, luaS_newlstr, etc. -- interpreter overhead |
|
||||
| 5.38% | Unresolved | WoW.exe code not in Ghidra symbol map |
|
||||
| 1.93% | Wine/System | ntdll, kernel32, wine internals |
|
||||
|
||||
## Hooked Functions (38 total, by self-time %)
|
||||
|
||||
### Already existed (6 hooks)
|
||||
| % | Address | Name | Convention |
|
||||
|---|---|---|---|
|
||||
| 2.80% | 0x714260 | transformMatrix4x4 | thiscall RET 0x10 |
|
||||
| 2.06% | 0x713d50 | findInterpolationIndices | thiscall RET 0x10 |
|
||||
| 0.73% | 0x707680 | renderFrame | thiscall RET 0x4 |
|
||||
| 0.44% | 0x713ea0 | interpolateAnimationKeyframes | fastcall RET 0x8 |
|
||||
| - | 0x708900 | executeSceneRenderPass | thiscall RET 0x4 |
|
||||
| - | 0x76FB00 | RenderTextureQuads | fastcall RET |
|
||||
| - | 0x616620 | CMovement::Process | thiscall RET 0x8 |
|
||||
|
||||
### New perf-identified hotspots (28 hooks)
|
||||
| % | Address | Name | Convention |
|
||||
|---|---|---|---|
|
||||
| 3.95% | 0x6318c0 | ClipPolygonToSinglePlane | stdcall RET 0x4 |
|
||||
| 3.65% | 0x5ca2d0 | GetOrCreateCharacterGlyph | stdcall RET 0x8 |
|
||||
| 1.73% | 0x7b2a50 | RenderParticleSprites | thiscall RET 0x8 |
|
||||
| 1.57% | 0x6abc40 | processLinkedListCollision | thiscall RET 0x8 |
|
||||
| 1.18% | 0x6afad0 | UpdateEntityAndChunksPositions | thiscall RET |
|
||||
| 1.15% | 0x765650 | renderAllFrameLayers | thiscall RET 0x4 |
|
||||
| 1.07% | 0x5ccbe0 | RenderTextToVertexBuffer | thiscall RET 0x18 |
|
||||
| 1.02% | 0x58a3d0 | RenderComplexGeometry | stdcall RET 0x24 |
|
||||
| 0.93% | 0x6c1f70 | updateEntitiesInBounds | thiscall RET 0x4 |
|
||||
| 0.88% | 0x5cdf40 | updateTextFrameCounter | thiscall RET |
|
||||
| 0.66% | 0x6816f0 | AddToSpatialGrid | thiscall RET |
|
||||
| 0.65% | 0x7c29f0 | ray_tri_intersect_idx_ushort | stdcall RET 0x10 |
|
||||
| 0.64% | 0x710b90 | ManageLinkedListNode | thiscall RET 0x4 |
|
||||
| 0.63% | 0x7b9b10 | calculateColorValues | thiscall RET 0x18 |
|
||||
| 0.61% | 0x686640 | SetVector3 | thiscall RET |
|
||||
| 0.59% | 0x6b8c60 | PerformSpatialCulling | thiscall RET 0x8 |
|
||||
| 0.59% | 0x6b88e0 | performCollisionDetection | thiscall RET 0x8 |
|
||||
| 0.55% | 0x7b5a10 | ProcessActiveParticles | stdcall RET 0x8 |
|
||||
| 0.53% | 0x404130 | CallbackIterator | stdcall RET 0x10 |
|
||||
| 0.50% | 0x464890 | FindObjectByGUID | stdcall RET 0x8 |
|
||||
| 0.49% | 0x632700 | RayTriangleIntersection | thiscall RET 0x20 |
|
||||
| 0.48% | 0x70cb30 | DrawBatchProj | thiscall RET |
|
||||
| 0.47% | 0x702000 | FindLuaFunction | stdcall RET 0x4 |
|
||||
| 0.44% | 0x5a0f50 | RenderSpriteQuads | thiscall RET 0xc |
|
||||
| 0.44% | 0x718960 | renderSceneNode | thiscall RET |
|
||||
| 0.44% | 0x6cffc0 | generateTerrainChunk | thiscall RET |
|
||||
| 0.43% | 0x593840 | D3D_SetTexture | thiscall RET 0x8 |
|
||||
| 0.42% | 0x6b8b70 | checkBoundingBoxIntersection | stdcall RET 0x8 |
|
||||
|
||||
### Unresolved-callee hooks (4 hooks)
|
||||
| % | Address | Name | Convention |
|
||||
|---|---|---|---|
|
||||
| ~0.5% | 0x7bdd60 | rotateMatrixByAxisAngle | thiscall RET 0xc |
|
||||
| ~0.1% | 0x632460 | BuildTrianglePlanes | thiscall RET 0xc |
|
||||
| ~0.2% | 0x7b3d20 | SetupParticleRendering | thiscall RET 0x4 |
|
||||
| ~0.2% | 0x5ce0c0 | renderTextLine | thiscall RET 0x10 |
|
||||
|
||||
## Unhooked Mid-Tier (50 functions, 13.15% total)
|
||||
|
||||
Not worth individual hooks -- too small or too high-frequency (hook overhead would distort):
|
||||
|
||||
| % | Name | Why not hook |
|
||||
|---|---|---|
|
||||
| 0.39% | compareRenderItemsExtended | Sort comparator, millions of calls |
|
||||
| 0.39% | GetCachedData | Cache accessor, extremely hot path |
|
||||
| 0.39% | raycastPickObjects | Moderate frequency |
|
||||
| 0.35% | inflateDecodeLiteralsAndLengths | Decompression, bursty |
|
||||
| 0.34% | UpdateParticlePhysics | Per-particle, very hot |
|
||||
| 0.34% | updateAnimationSystem | Could be interesting entry point |
|
||||
| 0.32% | ClntObjMgrObjectPtr | Object lookup, called everywhere |
|
||||
| 0.29% | multiplyMatrix4x4 | Tiny function, massive call count |
|
||||
| 0.26% | quickSortArray | Sort impl, millions of comparisons |
|
||||
| ... | (40 more at 0.15-0.31%) | |
|
||||
|
||||
## Key Insights
|
||||
|
||||
1. **GPU/Driver is 19%** -- nothing we can do about d3d9.dll/amdvlk overhead
|
||||
2. **Lua VM is 8.4%** -- addon code execution, not optimizable from DLL side
|
||||
3. **Frustum clipping (ClipPolygonToSinglePlane) is the #1 WoW hotspot at 3.95%** -- pure math, SSE candidate via binary patch (no hook overhead)
|
||||
4. **Font rendering (GetOrCreateCharacterGlyph) is #2 at 3.65%** -- potential cache optimization
|
||||
5. **Bone pipeline (t44 + findInterp + interpKf) totals ~5.3%** -- SSE interp hook overhead negates savings; binary patch or full t44 rewrite needed
|
||||
6. **Hook overhead matters** -- for functions called >10k/frame (lerp, matrix multiply, sort comparators), detour trampoline cost (~30 cycles) exceeds any savings
|
||||
|
||||
## Files
|
||||
|
||||
- `cycles.out` -- raw stack-collapsed perf data
|
||||
- `perf.data.perfparser` -- hotspot binary cache (5.3GB)
|
||||
- Ghidra symbols: `/media/faststore/tmp/Dis/symbols.nm`
|
||||
@@ -1007,7 +1007,7 @@ fn calcScaledInverse(this_mat: u32, out: u32, scale: f32) void {
|
||||
// mat3(offset_vec3*), mat4(scale_float_bits)
|
||||
// =============================================================================
|
||||
|
||||
export fn transformImpl_BASELINE(this: u32, mat1: u32, mat2: u32, mat3: u32, mat4: u32) callconv(.c) void {
|
||||
export fn transformImpl_BASELINE(this: u32, mat1: u32, mat2: u32, mat3: u32, mat4: u32) callconv(.{ .x86_thiscall = .{} }) void {
|
||||
|
||||
@setEvalBranchQuota(50000);
|
||||
// =========================================================================
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
// RTQ (RenderTextureQuads) full rendering pipeline
|
||||
// All functions in the per-item draw call chain
|
||||
//
|
||||
// Call chain per item:
|
||||
// RenderTextureQuads (0x76FB00) -- the outer loop
|
||||
// -> InitializeRenderingPipeline (0x58A2A0) -- stores vertCount, calls RenderComplexGeometry
|
||||
// -> RenderComplexGeometry (0x58A3D0) -- format detect, VB create/fill, DrawPrimitive
|
||||
// -> CreateVertexBuffer (0x58A140 -> 0x594500) -- pool VB allocation
|
||||
// -> LockVertexBuffer (0x58A080) -- vtable call to CGxDevice+0xA8
|
||||
// -> [per-vertex interleave loop]
|
||||
// -> UnlockVertexBuffer (0x58A0A0) -- vtable call to CGxDevice+0xAC
|
||||
// -> DrawPrimitive (0x58A7C0) -- state update + SetRenderingCommand
|
||||
// -> RenderVertexBuffer (0x58A2E0) -- creates INDEX VB, issues DrawIndexedPrimitive
|
||||
// -> CreateAndBindVertexBuffer (0x58A750) -- index VB (bufferType=1)
|
||||
// -> CallGfxDeviceMethod_Wrapper (0x58A830) -- actual D3D9 DrawIndexedPrimitive
|
||||
// -> EmptyRenderFunction (0x58A340) -- RET (no-op)
|
||||
|
||||
// === InitializeRenderingPipeline (0x58A2A0) -- 54 bytes ===
|
||||
// __fastcall(ECX=vertCount, EDX=xyzPtr, 11 stack params)
|
||||
// Stores vertCount to global g_currentPrimitiveType and tail-calls RenderComplexGeometry.
|
||||
void __fastcall InitializeRenderingPipeline(int vertCount, void** xyzPtr, /* ...11 stack params */)
|
||||
{
|
||||
g_currentPrimitiveType = (void*)vertCount; // stored at some global
|
||||
RenderComplexGeometry(vertCount, xyzPtr, /* forward all params */);
|
||||
}
|
||||
|
||||
// === CreateVertexBuffer wrapper (0x58A140) -- 24 bytes ===
|
||||
// __fastcall(ECX=bufferType, EDX=vertexSize, stack: vertexCount)
|
||||
// Thin wrapper: loads CGxDevice from global, calls D3D_CreateVertexBuffer.
|
||||
void __fastcall CreateVertexBuffer(int bufferType, int vertexSize, int vertexCount)
|
||||
{
|
||||
D3D_CreateVertexBuffer(CGxDeviceD3d__device, bufferType, vertexSize, vertexCount);
|
||||
}
|
||||
|
||||
// === D3D_CreateVertexBuffer (0x594500) -- 75 bytes ===
|
||||
// __thiscall(ECX=CGxDevice, stack: bufferType, vertexSize, vertexCount)
|
||||
// Returns a pool handle. The pool is indexed by bufferType at CGxDevice+0x26CC.
|
||||
// Reuses existing D3D9 VB unless the requested size exceeds current allocation.
|
||||
int __thiscall D3D_CreateVertexBuffer(void* this, int bufferType, int vertexSize, int vertexCount)
|
||||
{
|
||||
int poolHandle = *(int*)((int)this + bufferType * 4 + 0x26CC);
|
||||
int d3dVB = *(int*)(poolHandle + 8);
|
||||
if (d3dVB != 0 && *(uint*)(d3dVB + 0x10) < (uint)(vertexSize * vertexCount)) {
|
||||
// Existing VB too small -- resize via vtable call
|
||||
(*(code**)(*this + 0xA0))(d3dVB, vertexSize * vertexCount);
|
||||
}
|
||||
SetDimensionsAndSize(poolHandle, vertexSize, vertexCount);
|
||||
return poolHandle;
|
||||
}
|
||||
|
||||
// === SetDimensionsAndSize (0x5946F0) -- 32 bytes ===
|
||||
void SetDimensionsAndSize(int handle, int vertexSize, int vertexCount)
|
||||
{
|
||||
*(int*)(handle + 0x0C) = vertexSize;
|
||||
*(int*)(handle + 0x10) = vertexCount;
|
||||
*(int*)(handle + 0x14) = vertexSize * vertexCount;
|
||||
*(char*)(handle + 0x1C) = 0; // clear dirty flag
|
||||
}
|
||||
|
||||
// === LockVertexBuffer (0x58A080) -- 18 bytes ===
|
||||
// __fastcall(ECX=poolHandle)
|
||||
// Calls CGxDevice vtable[0xA8/4 = 42] to lock the D3D9 VB.
|
||||
// Returns pointer to locked VB memory.
|
||||
void* __fastcall LockVertexBuffer(void* poolHandle)
|
||||
{
|
||||
return (*(code**)(*(int*)CGxDeviceD3d__device + 0xA8))(poolHandle);
|
||||
}
|
||||
|
||||
// === UnlockVertexBuffer (0x58A0A0) -- 27 bytes ===
|
||||
// __fastcall(ECX=poolHandle, EDX=byteCount)
|
||||
// Calls CGxDevice vtable[0xAC/4 = 43] to unlock, then marks pool handle active.
|
||||
void __fastcall UnlockVertexBuffer(int poolHandle, int byteCount)
|
||||
{
|
||||
(*(code**)(*(int*)CGxDeviceD3d__device + 0xAC))(poolHandle, byteCount);
|
||||
SetObjectActiveFlag(poolHandle);
|
||||
}
|
||||
|
||||
// === UpdateBufferData (0x58A0C0) -- 57 bytes ===
|
||||
// __fastcall(ECX=poolHandle, EDX=srcData, stack: byteCount, unused)
|
||||
// Used by CreateAndBindVertexBuffer for INDEX buffer filling.
|
||||
// If byteCount==0, auto-computes from handle's vertexSize*vertexCount.
|
||||
void __fastcall UpdateBufferData(int poolHandle, void* srcData, int byteCount, void* unused)
|
||||
{
|
||||
if (byteCount == 0) {
|
||||
byteCount = *(int*)(poolHandle + 0x10) * *(int*)(poolHandle + 0x0C);
|
||||
}
|
||||
(*(code**)(*(int*)CGxDeviceD3d__device + 0xB0))(poolHandle, srcData, byteCount, unused);
|
||||
SetObjectActiveFlag(poolHandle);
|
||||
}
|
||||
|
||||
// === DrawPrimitive / GxDevice dispatch (0x58A7C0) -- 54 bytes ===
|
||||
// __fastcall(ECX=poolHandle, EDX=formatCode)
|
||||
// Reads per-format state from table at 0x809C00 (16 bytes per entry):
|
||||
// +0x00: ptr to state array (GxDevice render state descriptors)
|
||||
// +0x04: state array element count
|
||||
// +0x08: primitive type mapping
|
||||
// +0x0C: dirty flags bitmask
|
||||
// Applies state, marks dirty, stores draw command in CGxDevice for D3D9 submission.
|
||||
void __fastcall DrawPrimitive(int poolHandle, int formatCode)
|
||||
{
|
||||
int* stateTable = (int*)(0x809C00 + formatCode * 0x10);
|
||||
UpdateGfxStateArray(poolHandle, stateTable[0], stateTable[1]);
|
||||
MarkStateDirty(stateTable[3]);
|
||||
SetRenderingCommand(CGxDeviceD3d__device, poolHandle, formatCode);
|
||||
}
|
||||
|
||||
// === SetRenderingCommand (0x592AA0) -- 40 bytes ===
|
||||
// __thiscall(ECX=CGxDevice, stack: poolHandle, formatCode)
|
||||
// Stores the draw command into CGxDevice for later D3D9 submission.
|
||||
void __thiscall SetRenderingCommand(void* this, void* poolHandle, int formatCode)
|
||||
{
|
||||
*(int*)((int)this + 0x27E0) = formatCode;
|
||||
*(void**)((int)this + 0x27E4) = poolHandle;
|
||||
*(int*)((int)this + 0x27E8) = *(int*)(0x809C08 + formatCode * 0x10);
|
||||
}
|
||||
|
||||
// === RenderVertexBuffer (0x58A2E0) -- 82 bytes ===
|
||||
// __fastcall(ECX=primType, EDX=vertCount, stack: indexPtr)
|
||||
// Creates index VB (bufferType=1), binds it, issues DrawIndexedPrimitive.
|
||||
void __fastcall RenderVertexBuffer(int primType, int vertCount, void* indexPtr)
|
||||
{
|
||||
if (g_currentPrimitiveType != NULL) {
|
||||
CreateAndBindVertexBuffer(vertCount, indexPtr); // index VB
|
||||
short adjustedPrimType = (short)g_currentPrimitiveType - 1;
|
||||
// Build draw call struct on stack
|
||||
struct { void* primPtr; void* unused; short vertCount; short flags; } call;
|
||||
call.primPtr = primType;
|
||||
call.unused = NULL;
|
||||
call.vertCount = vertCount;
|
||||
call.flags = 0;
|
||||
CallGfxDeviceMethod_Wrapper(&call, 1); // -> D3D9 DrawIndexedPrimitive
|
||||
}
|
||||
}
|
||||
|
||||
// === CreateAndBindVertexBuffer (0x58A750) -- 44 bytes ===
|
||||
// __fastcall(ECX=vertCount, EDX=dataPtr)
|
||||
// Used for INDEX buffer (bufferType=1, vertexSize=2 = sizeof(u16)).
|
||||
void __fastcall CreateAndBindVertexBuffer(int vertCount, void* dataPtr)
|
||||
{
|
||||
int handle = CreateVertexBuffer(1, 2, vertCount); // pool slot 1, 2 bytes/index
|
||||
UpdateBufferData(handle, dataPtr, 0, NULL);
|
||||
SetStreamSource(handle); // bind as index stream
|
||||
}
|
||||
|
||||
// === Vertex format tables (from game memory) ===
|
||||
//
|
||||
// Stride table at 0x85A7A8 (indexed by format code):
|
||||
// fmt 0: stride=12 xyz only
|
||||
// fmt 1: stride=24 xyz + defaultTC
|
||||
// fmt 2: stride=28 xyz + defaultTC + additional(4)
|
||||
// fmt 3: stride=32 xyz + defaultTC + texcoord1(8)
|
||||
// fmt 4: stride=36 xyz + defaultTC + additional(4) + texcoord1(8)
|
||||
// fmt 5: stride=40 xyz + defaultTC + texcoord1(8) + texcoord2(8)
|
||||
// fmt 6: stride=44 xyz + defaultTC + additional(4) + texcoord1(8) + texcoord2(8)
|
||||
// fmt 7: stride=16 xyz + additional(4)
|
||||
// fmt 8: stride=24 xyz + additional(4) + texcoord1(8)
|
||||
// fmt 9: stride=32 xyz + additional(4) + texcoord1(8) + texcoord2(8)
|
||||
// fmt 10: stride=20 xyz + texcoord1(8)
|
||||
// fmt 11: stride=28 xyz + texcoord1(8) + texcoord2(8)
|
||||
//
|
||||
// Element offset table at 0x8097A8 (indexed by format*13 + element):
|
||||
// Element 0 = xyz position (always at offset 0)
|
||||
// Element 3 = defaultTexCoord
|
||||
// Element 4 = additionalData (color)
|
||||
// Element 5 = texcoord1
|
||||
// Element 6 = texcoord2
|
||||
// Value -1 = element not present in this format
|
||||
@@ -0,0 +1,166 @@
|
||||
// RenderComplexGeometry (0x58A3D0) -- 886 bytes
|
||||
// __fastcall(ECX=vertCount, EDX=xyzPtr, 11 stack params)
|
||||
//
|
||||
// Called from InitializeRenderingPipeline (0x58A2A0) which just stores
|
||||
// vertCount to global [0xC0ED2C] then tail-calls this function.
|
||||
//
|
||||
// Purpose: Determine vertex format from which input pointers are non-null,
|
||||
// create/reuse a pool VB, lock it, interleave all input arrays into the VB
|
||||
// at the computed stride, unlock, then issue a DrawPrimitive.
|
||||
//
|
||||
// Parameters (after fastcall mapping):
|
||||
// param_1 = vertCount (ECX)
|
||||
// param_2 = xyzPtr (EDX) -- 3 floats per vert, stride in param_3
|
||||
// param_3 = xyzStride (stack) -- typically 0x0C (12 bytes)
|
||||
// param_4 = defaultTexCoordPtr (stack) -- game constant at 0xCF4CF4, 3 floats/vert
|
||||
// param_5 = defaultTexCoordStride (stack) -- 0 means use param_4 as single value
|
||||
// param_6 = additionalDataPtr (stack) -- per-vert color (DWORD), or NULL
|
||||
// param_7 = additionalDataStride (stack)
|
||||
// param_8 = texCoord1Ptr (stack) -- unused in RTQ path
|
||||
// param_9 = texCoord1Stride (stack)
|
||||
// param_10 = texCoord2Ptr (stack) -- UV coords, 2 floats/vert
|
||||
// param_11 = texCoord2Stride (stack) -- typically 8
|
||||
//
|
||||
// Vertex format table:
|
||||
// Format codes 0-11, determined by which of param_4/6/8/10 are non-null.
|
||||
// Stride table at 0x85A7A8: [12,24,28,32,36,40,44,16,24,32,20,28]
|
||||
// Element offset table at 0x8097A8: indexed by (format*13 + element)*4
|
||||
// Elements: 0=xyz, 3=defaultTC, 4=additional, 5=texcoord1, 6=texcoord2
|
||||
//
|
||||
// For RTQ with additionalData (format 4, stride 36):
|
||||
// [0-11] xyz (12 bytes, 3 floats)
|
||||
// [12-23] defaultTC (12 bytes, 3 floats from 0xCF4CF4)
|
||||
// [24-27] additional (4 bytes, DWORD color)
|
||||
// [28-35] texcoord2 (8 bytes, 2 floats UV)
|
||||
//
|
||||
// For RTQ without additionalData (format 1, stride 24):
|
||||
// [0-11] xyz (12 bytes)
|
||||
// [12-23] defaultTC (12 bytes)
|
||||
//
|
||||
// Per-vertex loop:
|
||||
// 1. Copy xyz (3 dwords) at element offset 0
|
||||
// 2. Copy defaultTC (3 dwords) at element offset 3 (12 bytes)
|
||||
// 3. Check lighting flag at CGxDevice+0x258:
|
||||
// - If flag == 1: byte-swap color (BGRA -> RGBA or similar)
|
||||
// - Else: copy color as-is
|
||||
// 4. Copy additional data (1 dword) at element offset 4
|
||||
// 5. Copy texcoord1 (2 dwords) at element offset 5
|
||||
// 6. Copy texcoord2 (2 dwords) at element offset 6
|
||||
// Each pointer advances by its respective stride per vertex.
|
||||
// VB write pointer advances by the interleaved stride per vertex.
|
||||
//
|
||||
// After loop: UnlockVertexBuffer, then DrawPrimitive(poolHandle, formatCode)
|
||||
//
|
||||
// DrawPrimitive (0x58A7C0):
|
||||
// Reads from a per-format-code table at 0x809C00 (stride 0x10):
|
||||
// +0x00: state array ptr
|
||||
// +0x04: state array count
|
||||
// +0x08: D3D primitive type table index
|
||||
// +0x0C: dirty flags mask
|
||||
// Calls UpdateGfxStateArray to apply GxDevice state changes,
|
||||
// then MarkStateDirty, then SetRenderingCommand which stores
|
||||
// the draw command into CGxDevice+0x27E0..0x27E8 for later
|
||||
// submission to D3D9.
|
||||
//
|
||||
// Pool VB system (D3D_CreateVertexBuffer at 0x594500):
|
||||
// CGxDevice has pool slots at +0x26CC indexed by bufferType.
|
||||
// RenderComplexGeometry uses bufferType=0.
|
||||
// Pool handle struct:
|
||||
// +0x08: D3D9 IDirect3DVertexBuffer9*
|
||||
// +0x0C: vertexSize (bytes per vertex for this format)
|
||||
// +0x10: vertexCount
|
||||
// +0x14: total bytes (vertexSize * vertexCount)
|
||||
// +0x1C: dirty flag (cleared by SetDimensionsAndSize)
|
||||
// The pool VB is reused across calls. Only recreated if the
|
||||
// requested size (vertexSize * vertexCount) exceeds the current
|
||||
// allocation at +0x14. This means no D3D9 CreateVertexBuffer
|
||||
// overhead on normal frames.
|
||||
//
|
||||
// RenderVertexBuffer (0x58A2E0):
|
||||
// Called AFTER RenderComplexGeometry returns. Uses a DIFFERENT pool
|
||||
// (bufferType=1) for index data. Creates/binds an index VB with
|
||||
// the quad indices {0,1,2,0,2,3}, then calls DrawIndexedPrimitive
|
||||
// via CallGfxDeviceMethod_Wrapper.
|
||||
|
||||
void __fastcall
|
||||
RenderComplexGeometry(
|
||||
int vertCount, // ECX
|
||||
void** xyzPtr, // EDX
|
||||
int xyzStride, // [ebp+0x08]
|
||||
void** defaultTCPtr, // [ebp+0x0C]
|
||||
int defaultTCStride, // [ebp+0x10]
|
||||
void** additionalPtr, // [ebp+0x14]
|
||||
int additionalStride, // [ebp+0x18]
|
||||
void** texCoord1Ptr, // [ebp+0x1C]
|
||||
int texCoord1Stride, // [ebp+0x20]
|
||||
void** texCoord2Ptr, // [ebp+0x24]
|
||||
int texCoord2Stride) // [ebp+0x28]
|
||||
{
|
||||
// Step 1: Format detection -- determine which of the 12 interleaved
|
||||
// vertex formats to use based on which input pointers are non-null.
|
||||
int formatCode = 1; // default: xyz + defaultTC
|
||||
// Complex nested-if tree mapping (defaultTC, additional, tc1, tc2)
|
||||
// presence to format codes 0-11. See format table above.
|
||||
|
||||
// Step 2: Get stride and allocate pool VB
|
||||
int stride = GetDataPointerByIndex(formatCode); // stride table lookup
|
||||
void* poolHandle = CreateVertexBuffer(0, stride, vertCount);
|
||||
char* vbData = LockVertexBuffer(poolHandle);
|
||||
|
||||
// Step 3: Compute write pointers for each element within the VB
|
||||
char* xyzDst = vbData + GetMatrixElementPointer(formatCode, 0);
|
||||
char* tcDst = (defaultTCPtr) ? vbData + GetMatrixElementPointer(formatCode, 3) : &dummy;
|
||||
char* addDst = (additionalPtr) ? vbData + GetMatrixElementPointer(formatCode, 4) : &dummy;
|
||||
char* tc1Dst = (texCoord1Ptr) ? vbData + GetMatrixElementPointer(formatCode, 5) : &dummy;
|
||||
char* tc2Dst = (texCoord2Ptr) ? vbData + GetMatrixElementPointer(formatCode, 6) : &dummy;
|
||||
|
||||
// Per-element advance: stride if present, 0 if writing to dummy
|
||||
int tcAdv = defaultTCPtr ? stride : 0;
|
||||
int addAdv = additionalPtr ? stride : 0;
|
||||
int tc1Adv = texCoord1Ptr ? stride : 0;
|
||||
int tc2Adv = texCoord2Ptr ? stride : 0;
|
||||
|
||||
// Step 4: Per-vertex interleave loop
|
||||
for (int v = 0; v < vertCount; v++) {
|
||||
// XYZ: always 12 bytes (3 floats)
|
||||
*(int*)(xyzDst + 0) = *(int*)(xyzPtr + 0);
|
||||
*(int*)(xyzDst + 4) = *(int*)(xyzPtr + 4);
|
||||
*(int*)(xyzDst + 8) = *(int*)(xyzPtr + 8);
|
||||
xyzDst += stride;
|
||||
xyzPtr += xyzStride;
|
||||
|
||||
// DefaultTC: 12 bytes (3 floats)
|
||||
*(int*)(tcDst + 0) = *(int*)(defaultTCPtr + 0);
|
||||
*(int*)(tcDst + 4) = *(int*)(defaultTCPtr + 4);
|
||||
*(int*)(tcDst + 8) = *(int*)(defaultTCPtr + 8);
|
||||
tcDst += tcAdv;
|
||||
defaultTCPtr += defaultTCStride;
|
||||
|
||||
// Additional (color): conditional byte-swap based on lighting flag
|
||||
int lightingInfo = UpdateLightingOffset(); // returns CGxDevice + 0x23C
|
||||
if (*(int*)(lightingInfo + 0x1C) == 1) {
|
||||
// Byte swap: BGRA -> RGBA (swap bytes 0 and 2)
|
||||
*(int*)(addDst) = CONCAT(byte3, byte0, byte1, byte2);
|
||||
} else {
|
||||
*(int*)(addDst) = *(int*)(additionalPtr);
|
||||
}
|
||||
addDst += addAdv;
|
||||
additionalPtr += additionalStride;
|
||||
|
||||
// TexCoord1: 8 bytes (2 floats)
|
||||
*(int*)(tc1Dst + 0) = *(int*)(texCoord1Ptr + 0);
|
||||
*(int*)(tc1Dst + 4) = *(int*)(texCoord1Ptr + 4);
|
||||
tc1Dst += tc1Adv;
|
||||
texCoord1Ptr += texCoord1Stride;
|
||||
|
||||
// TexCoord2: 8 bytes (2 floats)
|
||||
*(int*)(tc2Dst + 0) = *(int*)(texCoord2Ptr + 0);
|
||||
*(int*)(tc2Dst + 4) = *(int*)(texCoord2Ptr + 4);
|
||||
tc2Dst += tc2Adv;
|
||||
texCoord2Ptr += texCoord2Stride;
|
||||
}
|
||||
|
||||
// Step 5: Finalize
|
||||
UnlockVertexBuffer(poolHandle, stride * vertCount);
|
||||
DrawPrimitive(poolHandle, formatCode);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,255 @@
|
||||
// =============================================================================
|
||||
// processLinkedListCollision @ 0x006abc40
|
||||
// Function range: 0x006abc40 -- 0x006abd88 (329 bytes)
|
||||
// Generated by Ghidra headless analysis
|
||||
// =============================================================================
|
||||
|
||||
// =============================================================================
|
||||
// SECTION 1: DECOMPILATION
|
||||
// =============================================================================
|
||||
|
||||
|
||||
undefined * __fastcall
|
||||
processLinkedListCollision(int *param_1,float *param_2,uint *param_3,uint param_4)
|
||||
|
||||
{
|
||||
int iVar1;
|
||||
uint uVar2;
|
||||
int iVar3;
|
||||
undefined *puVar4;
|
||||
undefined4 *puVar5;
|
||||
undefined **ppuVar6;
|
||||
undefined *local_28;
|
||||
undefined *local_24;
|
||||
undefined *local_20;
|
||||
undefined *local_1c;
|
||||
undefined *local_18;
|
||||
undefined *local_14;
|
||||
undefined *local_10;
|
||||
undefined *local_c;
|
||||
undefined *local_8;
|
||||
|
||||
if ((param_4 & 0xf0000f) != 0) {
|
||||
local_8 = (undefined *)param_1[2];
|
||||
local_10 = (undefined *)param_1;
|
||||
local_c = (undefined *)param_2;
|
||||
if ((((uint)local_8 & 1) != 0) || (local_8 == (undefined *)0x0)) {
|
||||
local_8 = (undefined *)0x0;
|
||||
}
|
||||
while ((puVar4 = local_8, ((uint)local_8 & 1) == 0 && (local_8 != (undefined *)0x0))) {
|
||||
iVar1 = *(int *)(local_8 + 4);
|
||||
if (((*(ushort *)(iVar1 + 0xc) & 0x100) == 0) &&
|
||||
((*(undefined **)(iVar1 + 0x8c) != PTR_00c89f20 && (*(int *)(iVar1 + 0x88) != 0)))) {
|
||||
if (*(int *)(iVar1 + 0x180) == 0 && *(int *)(iVar1 + 0x184) == 0) {
|
||||
uVar2 = param_4 & 0xf;
|
||||
}
|
||||
else {
|
||||
uVar2 = param_4 & 0xf00000;
|
||||
}
|
||||
if (uVar2 != 0) {
|
||||
if (-1 < (char)*(ushort *)(iVar1 + 0xc)) {
|
||||
return (undefined *)0x0;
|
||||
}
|
||||
puVar5 = (undefined4 *)(iVar1 + 0x14c);
|
||||
ppuVar6 = &local_28;
|
||||
for (iVar3 = 6; iVar3 != 0; iVar3 = iVar3 + -1) {
|
||||
*ppuVar6 = (undefined *)*puVar5;
|
||||
puVar5 = puVar5 + 1;
|
||||
ppuVar6 = ppuVar6 + 1;
|
||||
}
|
||||
if (((((float)local_28 < *(float *)(local_c + 0xc) !=
|
||||
((float)local_28 == *(float *)(local_c + 0xc))) &&
|
||||
((float)local_24 < *(float *)(local_c + 0x10) !=
|
||||
((float)local_24 == *(float *)(local_c + 0x10)))) &&
|
||||
((float)local_20 < *(float *)(local_c + 0x14) !=
|
||||
((float)local_20 == *(float *)(local_c + 0x14)))) &&
|
||||
(((*(float *)local_c <= (float)local_1c && (*(float *)(local_c + 4) <= (float)local_18)
|
||||
) && (*(float *)(local_c + 8) <= (float)local_14)))) {
|
||||
addGeometryToBuffer((float *)local_c,iVar1,param_3);
|
||||
puVar4 = local_8;
|
||||
}
|
||||
*(undefined **)(iVar1 + 0x8c) = PTR_00c89f20;
|
||||
}
|
||||
}
|
||||
local_8 = *(undefined **)(puVar4 + *(int *)local_10 + 4);
|
||||
}
|
||||
}
|
||||
return (undefined *)0x1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// SECTION 2: FULL DISASSEMBLY
|
||||
// =============================================================================
|
||||
//
|
||||
// 0x006abc40 55 PUSH EBP
|
||||
// 0x006abc41 8b ec MOV EBP,ESP
|
||||
// 0x006abc43 83 ec 24 SUB ESP,0x24
|
||||
// 0x006abc46 53 PUSH EBX
|
||||
// 0x006abc47 8b c1 MOV EAX,ECX
|
||||
// 0x006abc49 8b 4d 0c MOV ECX,dword ptr [EBP + 0xc]
|
||||
// 0x006abc4c f7 c1 0f 00 f0 00 TEST ECX,0xf0000f
|
||||
// 0x006abc52 56 PUSH ESI
|
||||
// 0x006abc53 57 PUSH EDI
|
||||
// 0x006abc54 89 55 f8 MOV dword ptr [EBP + -0x8],EDX
|
||||
// 0x006abc57 89 45 f4 MOV dword ptr [EBP + -0xc],EAX
|
||||
// 0x006abc5a 0f 84 1b 01 00 00 JZ 0x006abd7b
|
||||
// 0x006abc60 8b 40 08 MOV EAX,dword ptr [EAX + 0x8]
|
||||
// 0x006abc63 a8 01 TEST AL,0x1
|
||||
// 0x006abc65 75 04 JNZ 0x006abc6b
|
||||
// 0x006abc67 85 c0 TEST EAX,EAX
|
||||
// 0x006abc69 75 07 JNZ 0x006abc72
|
||||
// 0x006abc6b 33 d2 XOR EDX,EDX
|
||||
// 0x006abc6d 89 55 fc MOV dword ptr [EBP + -0x4],EDX
|
||||
// 0x006abc70 eb 06 JMP 0x006abc78
|
||||
// 0x006abc72 89 45 fc MOV dword ptr [EBP + -0x4],EAX
|
||||
// 0x006abc75 8b 55 fc MOV EDX,dword ptr [EBP + -0x4]
|
||||
// 0x006abc78 f6 c2 01 TEST DL,0x1
|
||||
// 0x006abc7b 0f 85 fa 00 00 00 JNZ 0x006abd7b
|
||||
// 0x006abc81 85 d2 TEST EDX,EDX
|
||||
// 0x006abc83 0f 84 f2 00 00 00 JZ 0x006abd7b
|
||||
// 0x006abc89 8b 5a 04 MOV EBX,dword ptr [EDX + 0x4]
|
||||
// 0x006abc8c 66 8b 43 0c MOV AX,word ptr [EBX + 0xc]
|
||||
// 0x006abc90 f6 c4 01 TEST AH,0x1
|
||||
// 0x006abc93 0f 85 c1 00 00 00 JNZ 0x006abd5a
|
||||
// 0x006abc99 8b 35 20 9f c8 00 MOV ESI,dword ptr [0x00c89f20]
|
||||
// 0x006abc9f 39 b3 8c 00 00 00 CMP dword ptr [EBX + 0x8c],ESI
|
||||
// 0x006abca5 0f 84 af 00 00 00 JZ 0x006abd5a
|
||||
// 0x006abcab 8b b3 88 00 00 00 MOV ESI,dword ptr [EBX + 0x88]
|
||||
// 0x006abcb1 85 f6 TEST ESI,ESI
|
||||
// 0x006abcb3 0f 84 a1 00 00 00 JZ 0x006abd5a
|
||||
// 0x006abcb9 8b b3 80 01 00 00 MOV ESI,dword ptr [EBX + 0x180]
|
||||
// 0x006abcbf 0b b3 84 01 00 00 OR ESI,dword ptr [EBX + 0x184]
|
||||
// 0x006abcc5 74 08 JZ 0x006abccf
|
||||
// 0x006abcc7 f7 c1 00 00 f0 00 TEST ECX,0xf00000
|
||||
// 0x006abccd eb 03 JMP 0x006abcd2
|
||||
// 0x006abccf f6 c1 0f TEST CL,0xf
|
||||
// 0x006abcd2 0f 84 82 00 00 00 JZ 0x006abd5a
|
||||
// 0x006abcd8 84 c0 TEST AL,AL
|
||||
// 0x006abcda 0f 89 90 00 00 00 JNS 0x006abd70
|
||||
// 0x006abce0 8d b3 4c 01 00 00 LEA ESI,[EBX + 0x14c]
|
||||
// 0x006abce6 b9 06 00 00 00 MOV ECX,0x6
|
||||
// 0x006abceb 8d 7d dc LEA EDI,[EBP + -0x24]
|
||||
// 0x006abcee f3 a5 MOVSD.REP ES:EDI,ESI
|
||||
// 0x006abcf0 d9 45 dc FLD float ptr [EBP + -0x24]
|
||||
// 0x006abcf3 8b 4d f8 MOV ECX,dword ptr [EBP + -0x8]
|
||||
// 0x006abcf6 d8 59 0c FCOMP float ptr [ECX + 0xc]
|
||||
// 0x006abcf9 df e0 FNSTSW AX
|
||||
// 0x006abcfb f6 c4 41 TEST AH,0x41
|
||||
// 0x006abcfe 7a 4e JP 0x006abd4e
|
||||
// 0x006abd00 d9 45 e0 FLD float ptr [EBP + -0x20]
|
||||
// 0x006abd03 d8 59 10 FCOMP float ptr [ECX + 0x10]
|
||||
// 0x006abd06 df e0 FNSTSW AX
|
||||
// 0x006abd08 f6 c4 41 TEST AH,0x41
|
||||
// 0x006abd0b 7a 41 JP 0x006abd4e
|
||||
// 0x006abd0d d9 45 e4 FLD float ptr [EBP + -0x1c]
|
||||
// 0x006abd10 d8 59 14 FCOMP float ptr [ECX + 0x14]
|
||||
// 0x006abd13 df e0 FNSTSW AX
|
||||
// 0x006abd15 f6 c4 41 TEST AH,0x41
|
||||
// 0x006abd18 7a 34 JP 0x006abd4e
|
||||
// 0x006abd1a d9 45 e8 FLD float ptr [EBP + -0x18]
|
||||
// 0x006abd1d d8 19 FCOMP float ptr [ECX]
|
||||
// 0x006abd1f df e0 FNSTSW AX
|
||||
// 0x006abd21 f6 c4 01 TEST AH,0x1
|
||||
// 0x006abd24 75 28 JNZ 0x006abd4e
|
||||
// 0x006abd26 d9 45 ec FLD float ptr [EBP + -0x14]
|
||||
// 0x006abd29 d8 59 04 FCOMP float ptr [ECX + 0x4]
|
||||
// 0x006abd2c df e0 FNSTSW AX
|
||||
// 0x006abd2e f6 c4 01 TEST AH,0x1
|
||||
// 0x006abd31 75 1b JNZ 0x006abd4e
|
||||
// 0x006abd33 d9 45 f0 FLD float ptr [EBP + -0x10]
|
||||
// 0x006abd36 d8 59 08 FCOMP float ptr [ECX + 0x8]
|
||||
// 0x006abd39 df e0 FNSTSW AX
|
||||
// 0x006abd3b f6 c4 01 TEST AH,0x1
|
||||
// 0x006abd3e 75 0e JNZ 0x006abd4e
|
||||
// 0x006abd40 8b 45 08 MOV EAX,dword ptr [EBP + 0x8]
|
||||
// 0x006abd43 50 PUSH EAX
|
||||
// 0x006abd44 8b d3 MOV EDX,EBX
|
||||
// 0x006abd46 e8 45 00 00 00 CALL 0x006abd90
|
||||
// 0x006abd4b 8b 55 fc MOV EDX,dword ptr [EBP + -0x4]
|
||||
// 0x006abd4e 8b 0d 20 9f c8 00 MOV ECX,dword ptr [0x00c89f20]
|
||||
// 0x006abd54 89 8b 8c 00 00 00 MOV dword ptr [EBX + 0x8c],ECX
|
||||
// 0x006abd5a 8b 45 f4 MOV EAX,dword ptr [EBP + -0xc]
|
||||
// 0x006abd5d 8b 00 MOV EAX,dword ptr [EAX]
|
||||
// 0x006abd5f 8b 4c 10 04 MOV ECX,dword ptr [EAX + EDX*0x1 + 0x4]
|
||||
// 0x006abd63 03 c2 ADD EAX,EDX
|
||||
// 0x006abd65 89 4d fc MOV dword ptr [EBP + -0x4],ECX
|
||||
// 0x006abd68 8b 4d 0c MOV ECX,dword ptr [EBP + 0xc]
|
||||
// 0x006abd6b e9 05 ff ff ff JMP 0x006abc75
|
||||
// 0x006abd70 5f POP EDI
|
||||
// 0x006abd71 5e POP ESI
|
||||
// 0x006abd72 33 c0 XOR EAX,EAX
|
||||
// 0x006abd74 5b POP EBX
|
||||
// 0x006abd75 8b e5 MOV ESP,EBP
|
||||
// 0x006abd77 5d POP EBP
|
||||
// 0x006abd78 c2 08 00 RET 0x8
|
||||
// 0x006abd7b 5f POP EDI
|
||||
// 0x006abd7c 5e POP ESI
|
||||
// 0x006abd7d b8 01 00 00 00 MOV EAX,0x1
|
||||
// 0x006abd82 5b POP EBX
|
||||
// 0x006abd83 8b e5 MOV ESP,EBP
|
||||
// 0x006abd85 5d POP EBP
|
||||
// 0x006abd86 c2 08 00 RET 0x8
|
||||
//
|
||||
// Total instructions: 108
|
||||
|
||||
// =============================================================================
|
||||
// SECTION 3: PROLOGUE (first 30 instructions)
|
||||
// =============================================================================
|
||||
//
|
||||
// 0x006abc40 55 PUSH EBP
|
||||
// 0x006abc41 8b ec MOV EBP,ESP
|
||||
// 0x006abc43 83 ec 24 SUB ESP,0x24
|
||||
// 0x006abc46 53 PUSH EBX
|
||||
// 0x006abc47 8b c1 MOV EAX,ECX
|
||||
// 0x006abc49 8b 4d 0c MOV ECX,dword ptr [EBP + 0xc]
|
||||
// 0x006abc4c f7 c1 0f 00 f0 00 TEST ECX,0xf0000f
|
||||
// 0x006abc52 56 PUSH ESI
|
||||
// 0x006abc53 57 PUSH EDI
|
||||
// 0x006abc54 89 55 f8 MOV dword ptr [EBP + -0x8],EDX
|
||||
// 0x006abc57 89 45 f4 MOV dword ptr [EBP + -0xc],EAX
|
||||
// 0x006abc5a 0f 84 1b 01 00 00 JZ 0x006abd7b
|
||||
// 0x006abc60 8b 40 08 MOV EAX,dword ptr [EAX + 0x8]
|
||||
// 0x006abc63 a8 01 TEST AL,0x1
|
||||
// 0x006abc65 75 04 JNZ 0x006abc6b
|
||||
// 0x006abc67 85 c0 TEST EAX,EAX
|
||||
// 0x006abc69 75 07 JNZ 0x006abc72
|
||||
// 0x006abc6b 33 d2 XOR EDX,EDX
|
||||
// 0x006abc6d 89 55 fc MOV dword ptr [EBP + -0x4],EDX
|
||||
// 0x006abc70 eb 06 JMP 0x006abc78
|
||||
// 0x006abc72 89 45 fc MOV dword ptr [EBP + -0x4],EAX
|
||||
// 0x006abc75 8b 55 fc MOV EDX,dword ptr [EBP + -0x4]
|
||||
// 0x006abc78 f6 c2 01 TEST DL,0x1
|
||||
// 0x006abc7b 0f 85 fa 00 00 00 JNZ 0x006abd7b
|
||||
// 0x006abc81 85 d2 TEST EDX,EDX
|
||||
// 0x006abc83 0f 84 f2 00 00 00 JZ 0x006abd7b
|
||||
// 0x006abc89 8b 5a 04 MOV EBX,dword ptr [EDX + 0x4]
|
||||
// 0x006abc8c 66 8b 43 0c MOV AX,word ptr [EBX + 0xc]
|
||||
// 0x006abc90 f6 c4 01 TEST AH,0x1
|
||||
// 0x006abc93 0f 85 c1 00 00 00 JNZ 0x006abd5a
|
||||
|
||||
// =============================================================================
|
||||
// SECTION 4: ALL RET INSTRUCTIONS (stack cleanup indicator)
|
||||
// =============================================================================
|
||||
//
|
||||
// 0x006abd78 c2 08 00 RET 0x8
|
||||
// 0x006abd86 c2 08 00 RET 0x8
|
||||
|
||||
// =============================================================================
|
||||
// SECTION 5: XREFS TO 0x006abc40 (callers)
|
||||
// =============================================================================
|
||||
//
|
||||
// 0x006aad4c [UNCONDITIONAL_CALL] in processGeometryBoundsCheck (0x006aaab0)
|
||||
// 0x006ab4a1 [UNCONDITIONAL_CALL] in processTerrainChunkMeshGeneration (0x006aadc0)
|
||||
//
|
||||
// Total callers: 2
|
||||
|
||||
// =============================================================================
|
||||
// SECTION 6: XREFS FROM 0x006abc40 (callees)
|
||||
// =============================================================================
|
||||
//
|
||||
// 0x006abd90 addGeometryToBuffer
|
||||
//
|
||||
// Total callees: 1
|
||||
|
||||
@@ -0,0 +1,659 @@
|
||||
// =============================================================================
|
||||
// renderTextToBuffer @ 0x005CDC20
|
||||
// Decompiled from WoW.exe 1.12.1 (build 5875) via Ghidra 11.4.2
|
||||
// Single caller of RenderTextToVertexBuffer (0x5CCBE0)
|
||||
// =============================================================================
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// CALLING CONVENTION (verified from assembly)
|
||||
// -----------------------------------------------------------------------------
|
||||
// __thiscall: ECX = this (text object ptr), saved to EBX immediately
|
||||
// 0x005cdc20 PUSH EBP
|
||||
// 0x005cdc21 MOV EBP,ESP
|
||||
// 0x005cdc23 SUB ESP,0x74
|
||||
// 0x005cdc26 PUSH EBX
|
||||
// 0x005cdc27 PUSH ESI
|
||||
// 0x005cdc28 MOV EBX,ECX <-- this ptr saved to EBX
|
||||
// ...
|
||||
// 0x005cdee8 RET <-- single RET, no stack cleanup = __thiscall (0 stack params)
|
||||
//
|
||||
// Signature: void __thiscall renderTextToBuffer(TextObject* this)
|
||||
// No stack parameters. Single RET (no RET N).
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// XREFS TO (callers)
|
||||
// -----------------------------------------------------------------------------
|
||||
// 0x005cd6aa from validateAndPrepareText (UNCONDITIONAL_CALL)
|
||||
// 0x005cd426 from GetVertexBufferData (UNCONDITIONAL_CALL)
|
||||
//
|
||||
// Two callers:
|
||||
// 1. validateAndPrepareText (0x5cd6aa) -- validation/preparation path
|
||||
// 2. GetVertexBufferData (0x5cd426) -- vertex buffer retrieval path
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// XREFS FROM (callees)
|
||||
// -----------------------------------------------------------------------------
|
||||
// 0x005c6fa0 ConvertPixelsToScreen
|
||||
// 0x0040a2b0 __ftol (float-to-long)
|
||||
// 0x005c2810 ParseTextFormatCodes
|
||||
// 0x005c7260 WrapTextToWidth
|
||||
// 0x005c7010 ConvertPixelsToScreenAlt
|
||||
// 0x005ccbe0 RenderTextToVertexBuffer <<<< the target
|
||||
// 0x005cd310 AddRectangleToBuffer
|
||||
// 0x005cdf70 finalizeTextLayout
|
||||
// 0x005cd4d0 renderFadeEffect
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// TEXT OBJECT FIELD MAP (offsets from this/EBX)
|
||||
// -----------------------------------------------------------------------------
|
||||
// +0x1c float lineHeight (or spacing-related metric)
|
||||
// +0x28 float xOffset (used when bit7 of flags is clear)
|
||||
// +0x2c float color/style data (passed to RenderTextToVertexBuffer)
|
||||
// +0x34 float indentOrShadow (used when flags bit0 is set)
|
||||
// +0x3c float maxWidth (passed to WrapTextToWidth)
|
||||
// +0x40 float maxHeight (vertical overflow check)
|
||||
// +0x44 void* fontObject (passed to WrapTextToWidth as ECX)
|
||||
// +0x48 char* textString (the actual text to render)
|
||||
// +0x54 int alignment (0=left, 1=center, 2=right)
|
||||
// +0x58 float some metric (initial value for local_c / line step)
|
||||
// +0x5c uint flags bitfield:
|
||||
// bit0: has indent/shadow
|
||||
// bit1 (0x02): single-line mode (breaks loop after first line)
|
||||
// bit5 (0x20): has fade effect
|
||||
// bit7 (0x80): pixel mode vs screen mode
|
||||
// +0x60 uint resultFlags (OR'd with per-line flags from RenderTextToVertexBuffer)
|
||||
// +0x68 int fadeStart (passed to renderFadeEffect)
|
||||
// +0x6c int fadeEnd (passed to renderFadeEffect)
|
||||
// +0x90 uint lineCountOutput (zeroed at start, not the dirty flag)
|
||||
// +0x9c int LINE COUNTER / DIRTY FLAG -- THE KEY FIELD
|
||||
// - Checked FIRST: if (this+0x9c != 0) return immediately
|
||||
// - Incremented after each line rendered
|
||||
// - Also incremented for format-code-only lines (ParseTextFormatCodes returns 2)
|
||||
// - Acts as both "already rendered" guard AND line counter
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// DIRTY/VALID FLAG ANALYSIS
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// The field at +0x9c is the critical gate. The function's VERY FIRST check is:
|
||||
//
|
||||
// if (this->field_0x9c != 0) return; // already rendered, skip
|
||||
// if (this->textString == NULL) return; // no text
|
||||
// if (*this->textString == '\0') return; // empty text
|
||||
//
|
||||
// Assembly proof:
|
||||
// 0x005cdc2a MOV EAX,dword ptr [EBX + 0x9c]
|
||||
// 0x005cdc33 CMP EAX,EDI ; EDI = 0
|
||||
// 0x005cdc35 JNZ 0x005cdee2 ; bail if non-zero
|
||||
// 0x005cdc3b MOV EAX,dword ptr [EBX + 0x48]
|
||||
// 0x005cdc3e CMP EAX,EDI
|
||||
// 0x005cdc40 JZ 0x005cdee2 ; bail if text ptr is NULL
|
||||
// 0x005cdc46 CMP byte ptr [EAX],0x0
|
||||
// 0x005cdc49 JZ 0x005cdee2 ; bail if text is empty
|
||||
//
|
||||
// Then +0x9c is INCREMENTED after each rendered line:
|
||||
// 0x005cde55 MOV ECX,dword ptr [EBX + 0x9c]
|
||||
// 0x005cde5e INC ECX
|
||||
// 0x005cde62 MOV dword ptr [EBX + 0x9c],ECX
|
||||
//
|
||||
// And also incremented for format-code lines (ParseTextFormatCodes == 2):
|
||||
// 0x005cdd81 MOV EAX,dword ptr [EBX + 0x9c]
|
||||
// 0x005cdd8c INC EAX
|
||||
// 0x005cdd90 MOV dword ptr [EBX + 0x9c],EAX
|
||||
//
|
||||
// CONCLUSION: +0x9c serves as BOTH:
|
||||
// 1. A "dirty/needs-render" flag (0 = needs render, non-zero = already done)
|
||||
// 2. A line counter (counts lines processed during rendering)
|
||||
//
|
||||
// To force re-render: set this->field_0x9c = 0
|
||||
// To prevent render: set this->field_0x9c = non-zero
|
||||
//
|
||||
// The callers (validateAndPrepareText, GetVertexBufferData) presumably
|
||||
// reset +0x9c to 0 when text changes, triggering re-render on next call.
|
||||
|
||||
// +0x90 is zeroed at entry:
|
||||
// 0x005cdc4f MOV dword ptr [EBX + 0x90],EDI ; = 0
|
||||
// This appears to be a separate output counter, not the dirty flag.
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// FLOW SUMMARY
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// 1. Guard: if +0x9c != 0 || textString is null/empty -> return
|
||||
// 2. Zero +0x90 (line output counter?)
|
||||
// 3. Compute vertical layout params from +0x1c, +0x58, flags
|
||||
// 4. Loop over text lines:
|
||||
// a. Check vertical overflow (accumulated height vs +0x40 maxHeight)
|
||||
// b. ParseTextFormatCodes -- handle color/format escapes (returns 2 = consumed)
|
||||
// c. WrapTextToWidth -- break text at word boundaries for +0x3c width
|
||||
// d. Handle alignment (+0x54): left(0), center(1), right(2) via ConvertPixelsToScreenAlt
|
||||
// e. CALL RenderTextToVertexBuffer(this, textPtr, charCount, &color, &offset, &flags, &state)
|
||||
// f. Increment +0x9c (line counter)
|
||||
// g. If state==2, call AddRectangleToBuffer (highlight/selection rect)
|
||||
// h. OR per-line flags into +0x60
|
||||
// i. If flags bit1 (single-line mode), break
|
||||
// j. Advance to next line
|
||||
// 5. Call finalizeTextLayout(this)
|
||||
// 6. If flags bit5 (fade), call renderFadeEffect(this, fadeStart, fadeEnd)
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// RenderTextToVertexBuffer CALL SITE DETAIL (at 0x5CDE50)
|
||||
// -----------------------------------------------------------------------------
|
||||
// __thiscall: ECX = this (text object)
|
||||
// Stack args (6, pushed right-to-left):
|
||||
// push &state (EBP-0x74, local_74 area -- tracks render state, value 2 = highlight)
|
||||
// push &flags (EBP-0x24, output flags OR'd into +0x60)
|
||||
// push charCount (EBP-0x18, from WrapTextToWidth output)
|
||||
// push &offset (EBP-0x48, vertical/horizontal position floats)
|
||||
// push &color (EBP-0x30, color/style data)
|
||||
// push textPtr (ESI, current position in text string)
|
||||
//
|
||||
// Assembly at call site:
|
||||
// 0x005cde39 LEA EAX,[EBP + -0x74]
|
||||
// 0x005cde3c PUSH EAX ; &state
|
||||
// 0x005cde3d LEA ECX,[EBP + -0x24]
|
||||
// 0x005cde40 PUSH ECX ; &flags
|
||||
// 0x005cde41 MOV ECX,dword ptr [EBP + -0x18]
|
||||
// 0x005cde44 LEA EDX,[EBP + -0x48]
|
||||
// 0x005cde47 PUSH EDX ; &offset
|
||||
// 0x005cde48 LEA EAX,[EBP + -0x30]
|
||||
// 0x005cde4b PUSH EAX ; &color
|
||||
// 0x005cde4c PUSH ECX ; charCount
|
||||
// 0x005cde4d PUSH ESI ; textPtr
|
||||
// 0x005cde4e MOV ECX,EBX ; this
|
||||
// 0x005cde50 CALL 0x005ccbe0 ; RenderTextToVertexBuffer
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// DECOMPILED C (Ghidra raw output, lightly annotated)
|
||||
// =============================================================================
|
||||
|
||||
/* WARNING: Variable defined which should be unmapped: local_88 */
|
||||
void __fastcall renderTextToBuffer(void *param_1) // ECX = this
|
||||
{
|
||||
byte bVar1;
|
||||
uint uVar2;
|
||||
undefined *puVar3;
|
||||
int iVar4;
|
||||
undefined **ppuVar5;
|
||||
byte *pbVar6;
|
||||
float unaff_EDI;
|
||||
undefined4 *puVar7;
|
||||
float10 extraout_ST0;
|
||||
float10 fVar8;
|
||||
float10 extraout_ST0_00;
|
||||
float10 extraout_ST0_01;
|
||||
float10 extraout_ST0_02;
|
||||
ulonglong uVar9;
|
||||
float10 *pfVar10;
|
||||
float fVar11;
|
||||
undefined *local_88;
|
||||
undefined *local_78;
|
||||
undefined *local_74;
|
||||
undefined *local_70;
|
||||
undefined *local_6c;
|
||||
undefined *local_68;
|
||||
undefined *local_4c;
|
||||
undefined *local_48;
|
||||
undefined *local_44;
|
||||
undefined *local_40;
|
||||
uint uStack_3c;
|
||||
undefined *local_38;
|
||||
undefined *local_34;
|
||||
undefined *local_30;
|
||||
undefined *local_2c;
|
||||
undefined *local_28;
|
||||
undefined *local_24;
|
||||
undefined *local_20;
|
||||
undefined *local_1c;
|
||||
undefined *local_18;
|
||||
undefined *local_14;
|
||||
undefined *local_10;
|
||||
undefined *local_c;
|
||||
byte local_5;
|
||||
|
||||
// --- GUARD: dirty/valid check ---
|
||||
if (((*(int *)((int)param_1 + 0x9c) != 0) || // already rendered?
|
||||
(*(char **)((int)param_1 + 0x48) == (char *)0x0)) || // no text ptr?
|
||||
(**(char **)((int)param_1 + 0x48) == '\0')) { // empty text?
|
||||
return;
|
||||
}
|
||||
|
||||
// --- Reset line output counter ---
|
||||
*(undefined4 *)((int)param_1 + 0x90) = 0;
|
||||
|
||||
// --- Read fade params ---
|
||||
local_2c = *(undefined **)((int)param_1 + 0x6c); // fadeEnd
|
||||
local_38 = *(undefined **)((int)param_1 + 0x68); // fadeStart
|
||||
|
||||
// --- Convert line height to screen coords ---
|
||||
ConvertPixelsToScreen(
|
||||
(void *)(*(uint *)((int)param_1 + 0x5c) >> 7 & 1),
|
||||
(float10 *)-*(float *)((int)param_1 + 0x1c),
|
||||
unaff_EDI);
|
||||
|
||||
uVar2 = *(uint *)((int)param_1 + 0x5c) & 0x80; // pixel mode flag
|
||||
local_4c = (undefined *)0x0;
|
||||
|
||||
if (uVar2 == 0) {
|
||||
local_44 = *(undefined **)((int)param_1 + 0x28); // xOffset
|
||||
local_48 = (undefined *)(float)extraout_ST0;
|
||||
} else {
|
||||
local_48 = (undefined *)0x0;
|
||||
local_44 = (undefined *)0x0;
|
||||
}
|
||||
|
||||
local_34 = *(undefined **)((int)param_1 + 0x2c); // color/style
|
||||
local_10 = *(undefined **)((int)param_1 + 0x58); // line step metric
|
||||
pbVar6 = *(byte **)((int)param_1 + 0x48); // text string ptr
|
||||
|
||||
// Init state vars
|
||||
local_78 = (undefined *)0x0;
|
||||
local_70 = (undefined *)0x0;
|
||||
local_68 = (undefined *)0x0;
|
||||
local_20 = (undefined *)0x0;
|
||||
local_1c = (undefined *)0x0;
|
||||
local_14 = (undefined *)0x0;
|
||||
|
||||
// Compute line height (pixel mode vs screen mode)
|
||||
if (uVar2 == 0) {
|
||||
// Screen mode: round to integer pixels, then back to screen coords
|
||||
local_40 = PTR_00c2b9a0;
|
||||
uStack_3c = 0;
|
||||
uVar9 = __ftol();
|
||||
local_40 = (undefined *)uVar9;
|
||||
uStack_3c = 0;
|
||||
local_18 = (undefined *)(float)(uVar9 & 0xffffffff);
|
||||
local_10 = (undefined *)(float)((float10)(uVar9 & 0xffffffff) / extraout_ST0_00);
|
||||
ConvertPixelsToScreen((void *)0x0, *(float10 **)((int)param_1 + 0x1c), unaff_EDI);
|
||||
fVar8 = extraout_ST0_01 + (float10)(float)local_18;
|
||||
} else {
|
||||
// Pixel mode: just add
|
||||
fVar8 = (float10)(float)local_10 + (float10)*(float *)((int)param_1 + 0x1c);
|
||||
}
|
||||
|
||||
local_c = (undefined *)(float)fVar8; // total line step (height + spacing)
|
||||
local_5 = 1; // first line flag
|
||||
local_74 = (undefined *)((float)local_c + (float)local_48); // current Y position
|
||||
|
||||
bVar1 = *pbVar6;
|
||||
local_18 = (undefined *)0x0; // accumulated vertical height
|
||||
local_6c = local_48;
|
||||
|
||||
// --- MAIN RENDERING LOOP: iterate over lines ---
|
||||
do {
|
||||
// Check: end of text OR vertical overflow
|
||||
if (((bVar1 == 0) ||
|
||||
(*(float *)((int)param_1 + 0x40) <= (float)local_18)) ||
|
||||
(local_18 = (undefined *)((float)local_18 + *(float *)((int)param_1 + 0x1c) + (float)local_10),
|
||||
bVar1 == 0))
|
||||
goto LAB_005cdebc; // done
|
||||
|
||||
// Parse format/color codes
|
||||
puVar3 = ParseTextFormatCodes(
|
||||
pbVar6, &local_30, (uint *)0x0,
|
||||
*(uint *)((int)param_1 + 0x5c), &uStack_3c);
|
||||
|
||||
local_14 = (undefined *)0x0;
|
||||
|
||||
if (puVar3 == (undefined *)0x2) {
|
||||
// Format code consumed entire segment -- adjust position, skip render
|
||||
local_48 = (undefined *)((float)local_48 - (float)local_c);
|
||||
*(int *)((int)param_1 + 0x9c) = *(int *)((int)param_1 + 0x9c) + 1; // increment line counter
|
||||
pbVar6 = pbVar6 + (int)local_30;
|
||||
} else {
|
||||
// Check word wrap flag
|
||||
if (((uint)*(float10 **)((int)param_1 + 0x5c) & 1) == 0) {
|
||||
local_24 = (undefined *)0x0;
|
||||
} else {
|
||||
local_24 = *(undefined **)((int)param_1 + 0x34); // indent
|
||||
}
|
||||
|
||||
pfVar10 = *(float10 **)((int)param_1 + 0x1c);
|
||||
|
||||
// Word-wrap the text to fit maxWidth
|
||||
WrapTextToWidth(
|
||||
*(float10 **)((int)param_1 + 0x44), // font
|
||||
pbVar6, // text
|
||||
pfVar10, // line height
|
||||
*(float *)((int)param_1 + 0x3c), // maxWidth
|
||||
(int *)&local_1c, // out: charCount
|
||||
(float *)&local_14, // out: line width
|
||||
&local_20, // out: next line ptr
|
||||
(float10 *)local_24, // indent
|
||||
*(float10 **)((int)param_1 + 0x5c), // flags
|
||||
&local_5); // first line flag
|
||||
|
||||
// Check if wrapping produced valid output
|
||||
if (((local_20 == pbVar6) || (local_20 == (undefined *)0x0)) ||
|
||||
((local_1c == (undefined *)0x0 && (*local_20 == '\0')))) {
|
||||
LAB_005cdebc:
|
||||
// --- FINALIZE ---
|
||||
finalizeTextLayout((int)param_1);
|
||||
if ((*(byte *)((int)param_1 + 0x5c) & 0x20) == 0) {
|
||||
return;
|
||||
}
|
||||
// Fade effect
|
||||
if ((local_38 == (undefined *)0xffffffff) &&
|
||||
(local_2c == (undefined *)0xffffffff)) {
|
||||
return;
|
||||
}
|
||||
renderFadeEffect(param_1, (int)local_38, (int)local_2c);
|
||||
return;
|
||||
}
|
||||
|
||||
// --- ALIGNMENT ---
|
||||
puVar3 = local_14;
|
||||
if (*(int *)((int)param_1 + 0x54) == 2) {
|
||||
// Right-aligned
|
||||
LAB_005cde14:
|
||||
ConvertPixelsToScreenAlt(
|
||||
(void *)(*(uint *)((int)param_1 + 0x5c) >> 7 & 1),
|
||||
(float10 *)-(float)puVar3, unaff_EDI);
|
||||
local_4c = (undefined *)(float)extraout_ST0_02;
|
||||
} else if (*(int *)((int)param_1 + 0x54) == 1) {
|
||||
// Center-aligned
|
||||
puVar3 = (undefined *)((float)local_14 * StaticFloat0_5);
|
||||
goto LAB_005cde14;
|
||||
}
|
||||
// else: left-aligned, local_4c stays 0
|
||||
|
||||
local_28 = (undefined *)0x0;
|
||||
if (local_78 != (undefined *)0x0) {
|
||||
local_70 = local_4c;
|
||||
}
|
||||
|
||||
fVar11 = 8.528623e-39; // junk / uninitialized
|
||||
puVar3 = local_1c;
|
||||
|
||||
// --- THE CALL: render this line's glyphs to vertex buffer ---
|
||||
RenderTextToVertexBuffer(
|
||||
param_1, // this (ECX)
|
||||
pbVar6, // textPtr (current line start)
|
||||
(int)local_1c, // charCount
|
||||
(uint *)&local_34, // &color/style
|
||||
(float *)&local_4c, // &position offset
|
||||
(uint *)&local_28, // &output flags
|
||||
(int *)&local_78); // &render state
|
||||
|
||||
// Increment line counter (+0x9c)
|
||||
*(int *)((int)param_1 + 0x9c) = *(int *)((int)param_1 + 0x9c) + 1;
|
||||
|
||||
// If state == 2, add highlight/selection rectangle
|
||||
if (local_78 == (undefined *)0x2) {
|
||||
ppuVar5 = &local_74;
|
||||
puVar7 = (undefined4 *)&stack0xffffff5c;
|
||||
for (iVar4 = 8; iVar4 != 0; iVar4 = iVar4 + -1) {
|
||||
*puVar7 = *ppuVar5;
|
||||
ppuVar5 = ppuVar5 + 1;
|
||||
puVar7 = puVar7 + 1;
|
||||
}
|
||||
AddRectangleToBuffer(param_1, (float)pfVar10, fVar11, (float)pbVar6, (float)puVar3);
|
||||
}
|
||||
|
||||
// Advance vertical position
|
||||
local_48 = (undefined *)((float)local_48 - (float)local_c);
|
||||
|
||||
// Accumulate result flags
|
||||
*(uint *)((int)param_1 + 0x60) = *(uint *)((int)param_1 + 0x60) | (uint)local_28;
|
||||
|
||||
// Move to next line
|
||||
pbVar6 = local_20;
|
||||
|
||||
// Single-line mode check: if bit1 set, done after first line
|
||||
if ((*(byte *)((int)param_1 + 0x5c) & 2) != 0)
|
||||
goto LAB_005cdebc;
|
||||
}
|
||||
|
||||
bVar1 = *pbVar6;
|
||||
local_6c = (undefined *)((float)local_6c - (float)local_c);
|
||||
local_74 = (undefined *)((float)local_74 - (float)local_c);
|
||||
} while (true);
|
||||
}
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// FULL DISASSEMBLY LISTING
|
||||
// =============================================================================
|
||||
//
|
||||
// 0x005cdc20 PUSH EBP
|
||||
// 0x005cdc21 MOV EBP,ESP
|
||||
// 0x005cdc23 SUB ESP,0x74
|
||||
// 0x005cdc26 PUSH EBX
|
||||
// 0x005cdc27 PUSH ESI
|
||||
// 0x005cdc28 MOV EBX,ECX
|
||||
// 0x005cdc2a MOV EAX,dword ptr [EBX + 0x9c]
|
||||
// 0x005cdc30 PUSH EDI
|
||||
// 0x005cdc31 XOR EDI,EDI
|
||||
// 0x005cdc33 CMP EAX,EDI
|
||||
// 0x005cdc35 JNZ 0x005cdee2
|
||||
// 0x005cdc3b MOV EAX,dword ptr [EBX + 0x48]
|
||||
// 0x005cdc3e CMP EAX,EDI
|
||||
// 0x005cdc40 JZ 0x005cdee2
|
||||
// 0x005cdc46 CMP byte ptr [EAX],0x0
|
||||
// 0x005cdc49 JZ 0x005cdee2
|
||||
// 0x005cdc4f MOV dword ptr [EBX + 0x90],EDI
|
||||
// 0x005cdc55 FLD float ptr [EBX + 0x1c]
|
||||
// 0x005cdc58 MOV ECX,dword ptr [EBX + 0x6c]
|
||||
// 0x005cdc5b FCHS
|
||||
// 0x005cdc5d MOV EAX,dword ptr [EBX + 0x68]
|
||||
// 0x005cdc60 PUSH ECX
|
||||
// 0x005cdc61 MOV dword ptr [EBP + -0x28],ECX
|
||||
// 0x005cdc64 FSTP float ptr [ESP]
|
||||
// 0x005cdc67 MOV ECX,dword ptr [EBX + 0x5c]
|
||||
// 0x005cdc6a SHR ECX,0x7
|
||||
// 0x005cdc6d AND ECX,0x1
|
||||
// 0x005cdc70 MOV dword ptr [EBP + -0x34],EAX
|
||||
// 0x005cdc73 CALL 0x005c6fa0
|
||||
// 0x005cdc78 MOV EAX,dword ptr [EBX + 0x5c]
|
||||
// 0x005cdc7b AND EAX,0x80
|
||||
// 0x005cdc80 MOV dword ptr [EBP + -0x48],EDI
|
||||
// 0x005cdc83 JZ 0x005cdc8f
|
||||
// 0x005cdc85 FSTP ST0
|
||||
// 0x005cdc87 MOV dword ptr [EBP + -0x44],EDI
|
||||
// 0x005cdc8a MOV dword ptr [EBP + -0x40],EDI
|
||||
// 0x005cdc8d JMP 0x005cdc98
|
||||
// 0x005cdc8f MOV EDX,dword ptr [EBX + 0x28]
|
||||
// 0x005cdc92 FSTP float ptr [EBP + -0x44]
|
||||
// 0x005cdc95 MOV dword ptr [EBP + -0x40],EDX
|
||||
// 0x005cdc98 CMP EAX,EDI
|
||||
// 0x005cdc9a MOV ECX,dword ptr [EBX + 0x2c]
|
||||
// 0x005cdc9d MOV EDX,dword ptr [EBX + 0x58]
|
||||
// 0x005cdca0 MOV ESI,dword ptr [EBX + 0x48]
|
||||
// 0x005cdca3 MOV dword ptr [EBP + -0x30],ECX
|
||||
// 0x005cdca6 MOV dword ptr [EBP + -0x74],EDI
|
||||
// 0x005cdca9 MOV dword ptr [EBP + -0x6c],0x0
|
||||
// 0x005cdcb0 MOV dword ptr [EBP + -0x64],0x0
|
||||
// 0x005cdcb7 MOV dword ptr [EBP + -0x1c],EDI
|
||||
// 0x005cdcba MOV dword ptr [EBP + -0x18],EDI
|
||||
// 0x005cdcbd MOV dword ptr [EBP + -0x10],0x0
|
||||
// 0x005cdcc4 MOV dword ptr [EBP + -0xc],EDX
|
||||
// 0x005cdcc7 JZ 0x005cdcd1
|
||||
// 0x005cdcc9 FLD float ptr [EBP + -0xc]
|
||||
// 0x005cdccc FADD float ptr [EBX + 0x1c]
|
||||
// 0x005cdccf JMP 0x005cdd10
|
||||
// 0x005cdcd1 MOV EAX,[0x00c2b9a0]
|
||||
// 0x005cdcd6 MOV dword ptr [EBP + -0x3c],EAX
|
||||
// 0x005cdcd9 MOV dword ptr [EBP + -0x38],EDI
|
||||
// 0x005cdcdc FILD qword ptr [EBP + -0x3c]
|
||||
// 0x005cdcdf FLD float ptr [EBP + -0xc]
|
||||
// 0x005cdce2 FMUL ST1
|
||||
// 0x005cdce4 FADD float ptr [0x00808120]
|
||||
// 0x005cdcea CALL 0x0040a2b0
|
||||
// 0x005cdcef MOV dword ptr [EBP + -0x3c],EAX
|
||||
// 0x005cdcf2 MOV dword ptr [EBP + -0x38],EDI
|
||||
// 0x005cdcf5 FILD qword ptr [EBP + -0x3c]
|
||||
// 0x005cdcf8 MOV ECX,dword ptr [EBX + 0x1c]
|
||||
// 0x005cdcfb PUSH ECX
|
||||
// 0x005cdcfc FST float ptr [EBP + -0x14]
|
||||
// 0x005cdcff XOR ECX,ECX
|
||||
// 0x005cdd01 FDIV ST0,ST1
|
||||
// 0x005cdd03 FSTP float ptr [EBP + -0xc]
|
||||
// 0x005cdd06 FSTP ST0
|
||||
// 0x005cdd08 CALL 0x005c6fa0
|
||||
// 0x005cdd0d FADD float ptr [EBP + -0x14]
|
||||
// 0x005cdd10 MOV EDX,dword ptr [EBP + -0x44]
|
||||
// 0x005cdd13 FSTP float ptr [EBP + -0x8]
|
||||
// 0x005cdd16 FLD float ptr [EBP + -0x8]
|
||||
// 0x005cdd19 MOV byte ptr [EBP + -0x1],0x1
|
||||
// 0x005cdd1d FADD float ptr [EBP + -0x44]
|
||||
// 0x005cdd20 MOV CL,byte ptr [ESI]
|
||||
// 0x005cdd22 TEST CL,CL
|
||||
// 0x005cdd24 MOV dword ptr [EBP + -0x68],EDX
|
||||
// 0x005cdd27 FSTP float ptr [EBP + -0x70]
|
||||
// 0x005cdd2a MOV dword ptr [EBP + -0x14],0x0
|
||||
// 0x005cdd31 JZ 0x005cdebc
|
||||
// 0x005cdd37 FLD float ptr [EBP + -0x14]
|
||||
// 0x005cdd3a FCOMP float ptr [EBX + 0x40]
|
||||
// 0x005cdd3d FNSTSW AX
|
||||
// 0x005cdd3f TEST AH,0x5
|
||||
// 0x005cdd42 JP 0x005cdebc
|
||||
// 0x005cdd48 TEST CL,CL
|
||||
// 0x005cdd4a FLD float ptr [EBP + -0x14]
|
||||
// 0x005cdd4d FADD float ptr [EBX + 0x1c]
|
||||
// 0x005cdd50 FADD float ptr [EBP + -0xc]
|
||||
// 0x005cdd53 FSTP float ptr [EBP + -0x14]
|
||||
// 0x005cdd56 JZ 0x005cdebc
|
||||
// 0x005cdd5c MOV ECX,dword ptr [EBX + 0x5c]
|
||||
// 0x005cdd5f LEA EAX,[EBP + -0x38]
|
||||
// 0x005cdd62 PUSH EAX
|
||||
// 0x005cdd63 PUSH ECX
|
||||
// 0x005cdd64 PUSH EDI
|
||||
// 0x005cdd65 LEA EDX,[EBP + -0x2c]
|
||||
// 0x005cdd68 MOV ECX,ESI
|
||||
// 0x005cdd6a CALL 0x005c2810
|
||||
// 0x005cdd6f CMP EAX,0x2
|
||||
// 0x005cdd72 MOV dword ptr [EBP + -0x10],0x0
|
||||
// 0x005cdd79 JNZ 0x005cdd9b
|
||||
// 0x005cdd7b FLD float ptr [EBP + -0x44]
|
||||
// 0x005cdd7e MOV ECX,dword ptr [EBP + -0x2c]
|
||||
// 0x005cdd81 MOV EAX,dword ptr [EBX + 0x9c]
|
||||
// 0x005cdd87 FSUB float ptr [EBP + -0x8]
|
||||
// 0x005cdd8a ADD ESI,ECX
|
||||
// 0x005cdd8c INC EAX
|
||||
// 0x005cdd8d FSTP float ptr [EBP + -0x44]
|
||||
// 0x005cdd90 MOV dword ptr [EBX + 0x9c],EAX
|
||||
// 0x005cdd96 JMP 0x005cdea0
|
||||
// 0x005cdd9b MOV EAX,dword ptr [EBX + 0x5c]
|
||||
// 0x005cdd9e TEST AL,0x1
|
||||
// 0x005cdda0 JZ 0x005cddaa
|
||||
// 0x005cdda2 MOV EDX,dword ptr [EBX + 0x34]
|
||||
// 0x005cdda5 MOV dword ptr [EBP + -0x20],EDX
|
||||
// 0x005cdda8 JMP 0x005cddb1
|
||||
// 0x005cddaa MOV dword ptr [EBP + -0x20],0x0
|
||||
// 0x005cddb1 MOV EDX,dword ptr [EBP + -0x20]
|
||||
// 0x005cddb4 LEA ECX,[EBP + -0x1]
|
||||
// 0x005cddb7 PUSH ECX
|
||||
// 0x005cddb8 PUSH EAX
|
||||
// 0x005cddb9 PUSH EDX
|
||||
// 0x005cddba LEA EAX,[EBP + -0x1c]
|
||||
// 0x005cddbd PUSH EAX
|
||||
// 0x005cddbe MOV EAX,dword ptr [EBX + 0x3c]
|
||||
// 0x005cddc1 LEA ECX,[EBP + -0x10]
|
||||
// 0x005cddc4 PUSH ECX
|
||||
// 0x005cddc5 MOV ECX,dword ptr [EBX + 0x1c]
|
||||
// 0x005cddc8 LEA EDX,[EBP + -0x18]
|
||||
// 0x005cddcb PUSH EDX
|
||||
// 0x005cddcc PUSH EAX
|
||||
// 0x005cddcd PUSH ECX
|
||||
// 0x005cddce MOV ECX,dword ptr [EBX + 0x44]
|
||||
// 0x005cddd1 MOV EDX,ESI
|
||||
// 0x005cddd3 CALL 0x005c7260
|
||||
// 0x005cddd8 MOV EAX,dword ptr [EBP + -0x1c]
|
||||
// 0x005cdddb CMP EAX,ESI
|
||||
// 0x005cdddd JZ 0x005cdebc
|
||||
// 0x005cdde3 CMP EAX,EDI
|
||||
// 0x005cdde5 JZ 0x005cdebc
|
||||
// 0x005cddeb CMP dword ptr [EBP + -0x18],EDI
|
||||
// 0x005cddee JNZ 0x005cddf9
|
||||
// 0x005cddf0 CMP byte ptr [EAX],0x0
|
||||
// 0x005cddf3 JZ 0x005cdebc
|
||||
// 0x005cddf9 MOV EAX,dword ptr [EBX + 0x54]
|
||||
// 0x005cddfc CMP EAX,0x2
|
||||
// 0x005cddff JNZ 0x005cde06
|
||||
// 0x005cde01 FLD float ptr [EBP + -0x10]
|
||||
// 0x005cde04 JMP 0x005cde14
|
||||
// 0x005cde06 CMP EAX,0x1
|
||||
// 0x005cde09 JNZ 0x005cde2b
|
||||
// 0x005cde0b FLD float ptr [EBP + -0x10]
|
||||
// 0x005cde0e FMUL float ptr [0x007ffa24]
|
||||
// 0x005cde14 PUSH ECX
|
||||
// 0x005cde15 FCHS
|
||||
// 0x005cde17 MOV ECX,dword ptr [EBX + 0x5c]
|
||||
// 0x005cde1a FSTP float ptr [ESP]
|
||||
// 0x005cde1d SHR ECX,0x7
|
||||
// 0x005cde20 AND ECX,0x1
|
||||
// 0x005cde23 CALL 0x005c7010
|
||||
// 0x005cde28 FSTP float ptr [EBP + -0x48]
|
||||
// 0x005cde2b CMP dword ptr [EBP + -0x74],EDI
|
||||
// 0x005cde2e MOV dword ptr [EBP + -0x24],EDI
|
||||
// 0x005cde31 JZ 0x005cde39
|
||||
// 0x005cde33 MOV EDX,dword ptr [EBP + -0x48]
|
||||
// 0x005cde36 MOV dword ptr [EBP + -0x6c],EDX
|
||||
// 0x005cde39 LEA EAX,[EBP + -0x74]
|
||||
// 0x005cde3c PUSH EAX
|
||||
// 0x005cde3d LEA ECX,[EBP + -0x24]
|
||||
// 0x005cde40 PUSH ECX
|
||||
// 0x005cde41 MOV ECX,dword ptr [EBP + -0x18]
|
||||
// 0x005cde44 LEA EDX,[EBP + -0x48]
|
||||
// 0x005cde47 PUSH EDX
|
||||
// 0x005cde48 LEA EAX,[EBP + -0x30]
|
||||
// 0x005cde4b PUSH EAX
|
||||
// 0x005cde4c PUSH ECX
|
||||
// 0x005cde4d PUSH ESI
|
||||
// 0x005cde4e MOV ECX,EBX
|
||||
// 0x005cde50 CALL 0x005ccbe0
|
||||
// 0x005cde55 MOV ECX,dword ptr [EBX + 0x9c]
|
||||
// 0x005cde5b MOV EAX,dword ptr [EBP + -0x74]
|
||||
// 0x005cde5e INC ECX
|
||||
// 0x005cde5f CMP EAX,0x2
|
||||
// 0x005cde62 MOV dword ptr [EBX + 0x9c],ECX
|
||||
// 0x005cde68 JNZ 0x005cde82
|
||||
// 0x005cde6a SUB ESP,0x20
|
||||
// 0x005cde6d MOV EDI,ESP
|
||||
// 0x005cde6f MOV ECX,0x8
|
||||
// 0x005cde74 LEA ESI,[EBP + -0x70]
|
||||
// 0x005cde77 MOVSD.REP ES:EDI,ESI
|
||||
// 0x005cde79 MOV ECX,EBX
|
||||
// 0x005cde7b CALL 0x005cd310
|
||||
// 0x005cde80 XOR EDI,EDI
|
||||
// 0x005cde82 FLD float ptr [EBP + -0x44]
|
||||
// 0x005cde85 MOV ECX,dword ptr [EBX + 0x60]
|
||||
// 0x005cde88 MOV EDX,dword ptr [EBP + -0x24]
|
||||
// 0x005cde8b FSUB float ptr [EBP + -0x8]
|
||||
// 0x005cde8e MOV AL,byte ptr [EBX + 0x5c]
|
||||
// 0x005cde91 MOV ESI,dword ptr [EBP + -0x1c]
|
||||
// 0x005cde94 OR ECX,EDX
|
||||
// 0x005cde96 FSTP float ptr [EBP + -0x44]
|
||||
// 0x005cde99 TEST AL,0x2
|
||||
// 0x005cde9b MOV dword ptr [EBX + 0x60],ECX
|
||||
// 0x005cde9e JNZ 0x005cdebc
|
||||
// 0x005cdea0 FLD float ptr [EBP + -0x68]
|
||||
// 0x005cdea3 MOV CL,byte ptr [ESI]
|
||||
// 0x005cdea5 TEST CL,CL
|
||||
// 0x005cdea7 FSUB float ptr [EBP + -0x8]
|
||||
// 0x005cdeaa FSTP float ptr [EBP + -0x68]
|
||||
// 0x005cdead FLD float ptr [EBP + -0x70]
|
||||
// 0x005cdeb0 FSUB float ptr [EBP + -0x8]
|
||||
// 0x005cdeb3 FSTP float ptr [EBP + -0x70]
|
||||
// 0x005cdeb6 JNZ 0x005cdd37
|
||||
// 0x005cdebc MOV ECX,EBX
|
||||
// 0x005cdebe CALL 0x005cdf70
|
||||
// 0x005cdec3 TEST byte ptr [EBX + 0x5c],0x20
|
||||
// 0x005cdec7 JZ 0x005cdee2
|
||||
// 0x005cdec9 MOV EAX,dword ptr [EBP + -0x34]
|
||||
// 0x005cdecc CMP EAX,-0x1
|
||||
// 0x005cdecf JNZ 0x005cded6
|
||||
// 0x005cded1 CMP dword ptr [EBP + -0x28],EAX
|
||||
// 0x005cded4 JZ 0x005cdee2
|
||||
// 0x005cded6 MOV ECX,dword ptr [EBP + -0x28]
|
||||
// 0x005cded9 PUSH ECX
|
||||
// 0x005cdeda PUSH EAX
|
||||
// 0x005cdedb MOV ECX,EBX
|
||||
// 0x005cdedd CALL 0x005cd4d0
|
||||
// 0x005cdee2 POP EDI
|
||||
// 0x005cdee3 POP ESI
|
||||
// 0x005cdee4 POP EBX
|
||||
// 0x005cdee5 MOV ESP,EBP
|
||||
// 0x005cdee7 POP EBP
|
||||
// 0x005cdee8 RET
|
||||
Reference in New Issue
Block a user