{"id": "D2Client.ScreenOpenMode", "kind": "global", "module": "D2Client", "rva": "0x11C414", "type": "int32", "status": "verified", "desc": "which side panel(s) open: 0=none,1/2/3=side/both; drives the L/R world-view shift; == nScreenPanels passed to the driver tile-draw fns", "source": ["mir:1.13C.txt", "sgd2freeres", "re:esoteric"], "refs": ["kb/reference/d2-re-reference-1.13c.md"]} {"id": "D2Client.GeneralPlayAreaCameraShiftX", "kind": "global", "module": "D2Client", "rva": "0x11C418", "type": "int32", "status": "verified", "desc": "offX: 0 with no panel, +/-DispW/4 (=320) with one; the native left-shift the mod KEEPS", "source": ["mir:1.13C.txt", "re:esoteric"]} {"id": "D2Client.RenderContextPtr", "kind": "global", "module": "D2Client", "rva": "0x11C3C4", "type": "ptr", "status": "verified", "desc": "*[this] = the render ctx (ONE struct): draw-window +0x04(L)/+0x08(T)/+0x0C(R)/+0x10(B), scroll +0x24/+0x28, dirty +0x00, visited-room grid +0xEA9C", "source": ["re:esoteric"]} {"id": "D2Client.GeneralDisplayWidth", "kind": "global", "module": "D2Client", "rva": "0xDBC48", "type": "int32", "status": "verified", "desc": "DispW=1280 (SGD2FreeRes). +4=height, +8=w-copy, +0xC=centerX, +0x10=centerY", "source": ["mir:1.13C.txt", "re:esoteric"]} {"id": "D2Client.PanelOpenArray", "kind": "global", "module": "D2Client", "rva": "0xFAD80", "type": "int32[]", "status": "verified", "desc": "per-panel open flags: inventory +4, char +8, skill +0x10, waypoint +0x50", "source": ["re:esoteric"]} {"id": "D2gfx.DriverInterfacePtr", "kind": "global", "module": "D2gfx", "rva": "0x11268", "type": "ptr", "status": "verified", "desc": "*[this] = the active video-driver dispatch struct (= D2Glide's 0x6F8649F0); slot +0x9c = the cel handler D2Client #10001 invokes", "source": ["re:esoteric"]} {"id": "D2Glide.DisplayWidth", "kind": "global", "module": "D2Glide", "rva": "0x15A68", "type": "int32", "status": "verified", "desc": "driver DisplayWidth; SGD2FreeRes rewrites 800->1280 at RVA 0xDCF1 at runtime; the -/4 math survives -> 960", "source": ["mir:1.13C.txt", "re:esoteric"]} {"id": "D2Glide.DisplayHeight", "kind": "global", "module": "D2Glide", "rva": "0x15B04", "type": "int32", "status": "verified", "desc": "driver DisplayHeight; stock 600, SGD2->720", "source": ["re:esoteric"]} {"id": "D2Glide.LiveDrawerGate", "kind": "global", "module": "D2Glide", "rva": "0x15A8C", "type": "ptr", "status": "verified", "desc": "[this]+4 / [this] gate the worker 0x7080: both-nonzero -> DEAD software drawer 0x6290; else -> LIVE drawer 0x6840", "source": ["re:esoteric"]} {"id": "D2Glide.DriverDispatchStruct", "kind": "global", "module": "D2Glide", "rva": "0x149F0", "type": "struct", "status": "verified", "desc": "the driver vtable D2gfx installs at [0x6FA91268]; +0x9c=0x6F8572F0 (cel handler)", "source": ["re:esoteric"]} {"id": "D2Glide.grDrawVertexArrayContiguous_IAT", "kind": "global", "module": "D2Glide", "rva": "0x111D0", "type": "iat_ptr", "status": "verified", "desc": "D2Glide IAT slot for glide3x!grDrawVertexArrayContiguous@16 (into D2DX). 0x6F856032 = jmp [this]. THE D2Glide->D2DX crossing; hook target for the pipeline-trace probe", "source": ["re:esoteric", "re:d2dx"]} {"id": "D2Client.DrawGame", "kind": "function", "module": "D2Client", "rva": "0x44230", "status": "verified", "desc": "main world render entry. body: PASS1(0x44302) -> tilesub(0x44307) -> PASS2(0x4436F, gated mode!=3) -> compositor(0x4437B) -> present #10040(0x443B9) -> RET(0x443BE)", "source": ["re:esoteric"]} {"id": "D2Client.Pass1Floor", "kind": "function", "module": "D2Client", "rva": "0x8B0C0", "status": "verified", "desc": "floor pass wrapper; esi=ctx, [esp+4]=bTilesOnly, ret 4; calls DrawRooms", "source": ["re:esoteric"]} {"id": "D2Client.Pass2WallsUnits", "kind": "function", "module": "D2Client", "rva": "0x8B110", "status": "verified", "desc": "wall/roof + unit pass; eax=CullingSpec; gated cmp[ScreenOpenMode],3;je", "source": ["re:esoteric"]} {"id": "D2Client.DrawRooms", "kind": "function", "module": "D2Client", "rva": "0x7A9F0", "status": "verified", "desc": "builds room-iteration RECT from ctx draw-window+scroll (band=[scrollX,scrollX+(R-L)]); per-tile cull skip if tileWorldX>RECT.R; grid helper 0x6FB2A0D0 sizes ctx+0xEAA8 (HEAP UAF trap on save/restore)", "source": ["re:esoteric"]} {"id": "D2Client.FloorFlush", "kind": "function", "module": "D2Client", "rva": "0x9ED50", "status": "verified", "desc": "floor tile flush; screenX=ctx+0x04-ctx+0x24+tileAbsX; NO inline clip; hands each tile to the cel blit thunks", "source": ["re:esoteric"]} {"id": "D2Client.CelBlitThunkOpaque", "kind": "function", "module": "D2Client", "rva": "0xD0D2", "expect": "FF 25 3C EC B7 6F", "status": "verified", "desc": "jmp [IAT 0x6FB7EC3C] -> D2gfx #10001. TILE-DEDICATED; the TILEBAND/GROUND-COLLECT counter hook site", "source": ["re:esoteric"]} {"id": "D2Client.CelBlitThunkAlpha", "kind": "function", "module": "D2Client", "rva": "0xD0D8", "expect": "FF 25 40 EC B7 6F", "status": "verified", "desc": "jmp [IAT 0x6FB7EC40] -> D2gfx #10058 (alpha)", "source": ["re:esoteric"]} {"id": "D2gfx.CelDrawOpaque_10001", "kind": "function", "module": "D2gfx", "ordinal": 10001, "rva": "0xBB50", "status": "verified", "desc": "mov eax,[0x6FA91268]; call [eax+0x9c]; ret 0x14 -- thin forwarder into the driver cel handler, no clip", "source": ["re:esoteric"]} {"id": "D2gfx.Fill_10041", "kind": "function", "module": "D2gfx", "ordinal": 10041, "rva": "0xB080", "status": "verified", "desc": "solid fill; forwarder to driver vtable +0x84; 295 D2Client callers, none targets [960,1280] (overdraw ruled out)", "source": ["re:esoteric"]} {"id": "D2Glide.DriverInit_10000", "kind": "function", "module": "D2Glide", "ordinal": 10000, "rva": "0x92D0", "expect": "B8 F0 49 86 6F C3", "status": "verified", "desc": "the ONLY export: mov eax,0x6F8649F0; ret -- hands D2gfx the driver dispatch struct", "source": ["re:esoteric"]} {"id": "D2Glide.LiveCelHandler", "kind": "function", "module": "D2Glide", "rva": "0x72F0", "status": "verified", "desc": "pfTileDrawLit (dispatch struct +0x9c); the live cel handler D2Client #10001 reaches; calls worker 0x7080", "source": ["re:esoteric"]} {"id": "D2Glide.Worker", "kind": "function", "module": "D2Glide", "rva": "0x7080", "status": "verified", "desc": "gates on [0x6F865A8C]: null -> LIVE drawer 0x6840; non-null -> DEAD 0x6290", "source": ["re:esoteric"]} {"id": "D2Glide.LiveDrawer", "kind": "function", "module": "D2Glide", "rva": "0x6840", "status": "inferred", "desc": "THE live cel->vertex drawer (confirmed fires: [GLIDECULL] edx=ScreenOpenMode). Per-subtile cull vs [esp+0x30]left,[esp+0x38]right narrowed by panel-mode (mode1 right=DispW/2=640 @0x6889, mode2 left=DispW/2-0x20=608 @0x689E). v1.9.1 NOP'd both -> NO visual change => this cull is world-space, NOT the screen clip. Submits via grDrawVertexArrayContiguous", "source": ["re:esoteric"]} {"id": "D2Glide.DeadSoftwareDrawer", "kind": "function", "module": "D2Glide", "rva": "0x6290", "status": "decoy", "desc": "DECOY -- DO NOT HOOK. Software/LFB drawer reached only via the non-taken branch of worker 0x7080; PROVEN dead (v1.9.0 hook never fired). Computes DisplayWidth-DisplayWidth/4=960 but never executes -- the 960 was mis-inferred off this dead code", "source": ["re:esoteric"], "trust": "verified"} {"id": "D2Glide.DeadTwin", "kind": "function", "module": "D2Glide", "rva": "0x61D0", "status": "decoy", "desc": "DECOY -- DO NOT HOOK. Uncalled twin of 0x6290 (0 E8/dword refs); identical width math; register-arg convention. Dead", "source": ["re:esoteric"], "trust": "verified"} {"id": "hook.PanelWorldWiden", "kind": "hook", "module": "D2Client", "rva": "0x44302", "expect": "E8 B9 6D 04 00", "feature": "PanelWorldWiden", "hookkind": "detour", "status": "active", "desc": "detour the base `call PASS1` to widen ctx+0x0C->DispW before PASS1 (issues floor tiles to screenX ~1236). NECESSARY but not sufficient (strip still black -- downstream clip)", "source": ["re:esoteric"]} {"id": "hook.PanelWorldGlideCull1", "kind": "hook", "module": "D2Glide", "rva": "0x6889", "expect": "89 4C 24 38", "patch": "90 90 90 90", "feature": "PanelWorldGlideUnclamp", "hookkind": "nop-store", "status": "failed", "desc": "NOP the mode-1 right-narrow store in the live drawer. v1.9.1: applied cleanly, NO visual change -> the cull isn't the screen clip. FAILED attempt", "source": ["re:esoteric"]} {"id": "hook.PanelWorldGlideCull2", "kind": "hook", "module": "D2Glide", "rva": "0x689E", "expect": "89 5C 24 30", "patch": "90 90 90 90", "feature": "PanelWorldGlideUnclamp", "hookkind": "nop-store", "status": "failed", "desc": "NOP the mode-2 left-narrow store. Same v1.9.1 FAILED result", "source": ["re:esoteric"]} {"id": "glide3x.grDrawVertexArrayContiguous", "kind": "function", "module": "glide3x", "status": "verified", "desc": "D2DX Glide-vertex submit = the D2Glide->D2DX crossing. PROBE v1.10.0 (filtered to the tile drawer by return-addr): floor geometry crosses at max screenX 1296, ~138 verts/frame in dead-zone [960,1280). The world geometry REACHES D2DX past 960 yet renders BLACK -> the panel-world clip is IN D2DX (m2 was right).", "source": ["re:esoteric", "re:d2dx"]} {"id": "glide3x.gameSize", "kind": "note", "module": "glide3x", "status": "verified", "desc": "D2DX Metrics.cpp: desktop 1280x720 -> gameSize={960,720} (narrow), gameSizeWide={1280,720}. 960 = the narrow render target. Chosen by GetSuggestedGameSize(desktop, wide=!NoWide) (D2DXContext.cpp:1170); d2dx.cfg nowide=false + [game]size=[1280,720] should force 1280 -- CONFIRM at runtime.", "source": ["d2dx:Metrics.cpp:17-19", "d2dx:D2DXContext.cpp:1170"]} {"id": "glide3x.SurfaceIdTracker_retag", "kind": "note", "module": "glide3x", "status": "unconfirmed", "desc": "SurfaceIdTracker.cpp:88: ScreenOpenMode&1 (panel open) && minx>=gameSize.width/2 (=640) RETAGS a world batch surfaceId=USER_INTERFACE. Prior audit said 'only tags, no cull' -- but the visible world clips ~640 with a panel open, so re-examine whether the UI-tag changes world compositing/clipping. Prime suspect.", "source": ["d2dx:SurfaceIdTracker.cpp:88"]} {"id": "finding.panelworld_clip_in_d2dx", "kind": "finding", "status": "verified", "desc": "2026-07-12 (v1.10.0 probe): the panel-world dead-zone clip is IN D2DX. Floor geometry crosses grDrawVertexArrayContiguous at max 1296 (138 verts in [960,1280)) yet the dead zone is BLACK. NOT D2Client (issues 1236), NOT D2Glide (submits past 960). The [640,960] tiles render via the SAME path, so the [960,1280] verts are valid, not degenerate -> D2DX clips them. Fix belongs at D2DX via a runtime glide3x hook from esoteric.dll (rebuild not available here).", "source": ["re:esoteric"]} {"id": "glide3x.grSstWinOpen", "kind": "function", "module": "glide3x", "ordinal": 66, "rva": "0xD970", "status": "verified", "desc": "D2DX grSstWinOpen (export _grSstWinOpen@28). OnSstWinOpen consumes _customGameSize as gameSize (D2DXContext.cpp:176-180) then creates/sizes the RenderContext. THE fix hook site: detour entry, call SetCustomResolution(1280,720) before delegating so the world target opens WIDE. Prologue 55 8B EC 6A FF (push ebp;mov ebp,esp;push -1).", "source": ["d2dx:glide3x.cpp", "re:esoteric"]} {"id": "glide3x.D2DXGetConfigurator", "kind": "function", "module": "glide3x", "ordinal": 1, "rva": "0x7850", "status": "verified", "desc": "exported _D2DXGetConfigurator@0 (NOT @4 -- the header D2DXConfigurator.h:98 string is a bug; use @0 or ordinal 1). Returns ID2DXConfigurator*; vtable [0]QI [1]AddRef [2]Release [3]SetCustomResolution(w,h) __stdcall. SetCustomResolution sets _customGameSize (a flag consumed at the next grSstWinOpen).", "source": ["d2dx:D2DXConfigurator.cpp:67-81", "re:esoteric"]} {"id": "hook.D2DXWiden", "kind": "hook", "module": "glide3x", "rva": "0xD970", "expect": "55 8B EC 6A FF", "feature": "D2DXWiden", "hookkind": "detour", "status": "experimental", "desc": "v1.11.0 THE FIX: detour grSstWinOpen; before each open call ID2DXConfigurator::SetCustomResolution(1280,720) so D2DX opens its WIDE game target (1280 vs the narrow 960 that clipped the world). Installed by a thread that waits for glide3x (late video driver). glide3x relocates -> resolve by export/ordinal. Keeps the native left-shift (it's in the submitted vertices). Awaiting Doug's test.", "source": ["re:esoteric"]} {"id": "finding.d2dx_gamesize_960_is_the_clip", "kind": "finding", "status": "verified", "desc": "2026-07-12 (workflow d2dx-panel-clip-fix, source+bytes): D2DX renders the world into its NARROW _gameSize={960,720} (Metrics.cpp desktop 1280x720). Clip cutoff == 960 == _gameSize.width: framebuffer sized to gameSize (SetFramebufferSize), UpdateViewport sets RSSetViewports+RSSetScissorRects to that rect, GameVS.hlsl NDC.x/960 -> x>=960 off-RT+out-of-scissor+NDC>1, rasterizer-clipped. The SurfaceIdTracker retag (minx>=gameSize/2) is a RED HERRING (surfaceId only feeds FXAA, color write unconditional). Fix = force gameSizeWide via SetCustomResolution(1280,720).", "source": ["d2dx:Metrics.cpp:16-20", "d2dx:RenderContext.cpp:516,674-686,1041", "d2dx:SurfaceIdTracker.cpp:88"]} {"id": "finding.panelopen_clip_is_d2glide_640", "kind": "finding", "status": "superseded", "desc": "[SUPERSEDED 2026-07-12: the 640 was the CULL with GlideUnclamp=0. Gated probe with GlideUnclamp=1 -> submit 1264, 338 verts in the dead zone, still black => the binding clip is a D2DX-downstream DROP, not D2Glide 640.] CORRECTION 2026-07-12 (v1.10.0 probe, PANEL-OPEN frames): with a panel open, the D2Glide live drawer 0x6F856840 submits floor geometry to grDrawVertexArrayContiguous at max screenX ONLY 640 (=DisplayWidth/2, the mode-1 right bound), band[960,1280)=0. D2Client still ISSUES to 1280 (TILEBAND). So the binding panel-open clip is D2Glide 0x856840 at 640, NOT D2DX. My earlier 'crosses at 1296 -> D2DX' read used NO-PANEL frames (before [WIDEN] mode=1) by mistake -- the harness was right, I read the wrong frames. finding.panelworld_clip_in_d2dx and finding.d2dx_gamesize_960 describe the NO-PANEL/second clip; the panel-open lever is here. Likely TWO clips: D2Glide 640 (panel) + D2DX 960 target; both need fixing. v1.9.1 cull-NOP showed no visual change -> re-testing GlideUnclamp WITH the probe to see if it widens the submit past 640 (cull-skip) or the 640 is a vertex-X clamp elsewhere in 0x856840.", "source": ["re:esoteric"]} {"id": "OQ.panelopen_640_cull_vs_clamp", "kind": "openquestion", "status": "closed", "desc": "Panel open: is the D2Glide floor submit clamped at 640(=DispW/2) by the [esp+0x38] per-subtile CULL (NOP-able @0x856889) or by a VERTEX-X CLAMP elsewhere in 0x856840's projection? v1.11.2 gated probe (GlideUnclamp=1) settles it: submit max ~1280 => cull is the lever; ~640 => clamp is elsewhere. ==> ANSWER: It's the CULL. v1.11.2 gated probe (mode=1): GlideUnclamp=1 -> panel-open D2Glide floor submit max 1264-1296 with 338 verts IN [960,1280); GlideUnclamp=0 was 640. The NOP defeats the cull (640->1264). The remaining black is a DROP at/after D2DX -- geometry reaches the dead zone, D2DX doesn't paint it.", "refs": ["finding.panelopen_clip_is_d2glide_640", "D2Glide.LiveDrawer"]} {"id": "OQ.glideunclamp_no_change", "kind": "openquestion", "status": "closed", "desc": "Why did v1.9.1/v1.11.0 GlideUnclamp (NOP the cull narrowing 0x856889/0x85689E) show NO visual change if 640 is the cull? Either the NOP widens the submit but a downstream layer hides it, or 640 comes from a clamp the NOP doesn't touch. Depends on OQ.panelopen_640_cull_vs_clamp. ==> ANSWER: GlideUnclamp DOES widen the submit (640->1264, 338 verts into the dead zone) -- never 'no effect'. The visual didn't change because the widened geometry is dropped downstream at/after D2DX.", "refs": ["hook.PanelWorldGlideCull1", "hook.PanelWorldGlideCull2"]} {"id": "OQ.d2dx_runtime_gamesize", "kind": "openquestion", "status": "open", "desc": "DISPUTES finding.d2dx_gamesize_960. What is D2DX's ACTUAL runtime gameSize in-game (panel open)? Workflow inferred 960 (narrow). But forcing 1280 via SetCustomResolution (D2DXWiden) SHRANK the menu (black margin) -> implies native was LARGER than 1280, contradicting 960. Need a runtime read (probe gameSize / grSstWinOpen args), not source inference.", "refs": ["finding.d2dx_gamesize_960_is_the_clip", "glide3x.gameSize", "OQ.menu_res_regression"]} {"id": "OQ.units_shift_left", "kind": "openquestion", "status": "open", "desc": "Units/NPCs shift LEFT on inventory-open (they must NOT shift). Source unknown: the ctx+0x0C widen, D2DXWiden (now reverted), or the double-motion-smoothing (d2fps+D2DX both on). Re-check with D2DXWiden off. ==> PROGRESS 2026-07-12: terrain shift CONFIRMED = -320 (1x) via offX(0x6FBCC418)->ctx+0x04; scrollX untouched. Shared tile projection is 1x for all layers, so the objects' extra -320 is downstream/unit-specific. STILL OPEN: unit-layer re-read of offX (theory a) vs motion-smoothing (theory b). NEXT: xref offX reads -- if the unit/PASS2 path reads 0x6FBCC418 too, theory (a). ==> 2026-07-12 xref: offX read 173x, 1 write (0x6FB5AF7C). Attempt A (offX=0) un-shifted floor+units but NOT walls (separate source) + broke clicks. Shift is MULTI-SOURCE + hit-test-coupled; units lean theory (a). Naive offX-kill is OUT.", "refs": []} {"id": "OQ.one_clip_or_two", "kind": "openquestion", "status": "open", "desc": "ONE clip (D2Glide 640) or TWO (D2Glide 640 + a D2DX target)? Panel-open probe=640, no-panel probe=1296 => the D2Glide clip is panel-mode-dependent. Whether D2DX ALSO clips once geometry passes 640 is blocked by OQ.d2dx_runtime_gamesize.", "refs": ["finding.panelopen_clip_is_d2glide_640"]} {"id": "OQ.menu_res_regression", "kind": "openquestion", "status": "open", "desc": "D2DXWiden(1280) regressed the menu resolution. Is forcing 1280 wrong for the low-res menu, or is the game's native size >1280? Ties to OQ.d2dx_runtime_gamesize. If D2DXWiden is re-applied, scope it IN-GAME only.", "refs": ["hook.D2DXWiden"]} {"id": "council.wave4_consensus", "kind": "finding", "status": "noted", "desc": "Council wave-4 (chat m5 + clau m6 converge): the panel-open dead zone is the 960-WIDE RENDER-TARGET EXTENT, not a surfaceId routing/split. D2Glide announces 960 gameSize to D2DX at grSstWinOpen; SGD2FreeRes widened D2 to 1280 without updating that; D2DX allocates a 960 world RT and clips the 1280-coord floor. Fix they gave = D2DXGetConfigurator->SetCustomResolution(1280,720) before grSstWinOpen. STATUS: we BUILT this (feature_d2dx.c / D2DXWiden) -> 122 successful calls but it REGRESSED the menu res and did NOT fill. So their consensus fix is tested-and-insufficient.", "refs": ["hook.D2DXWiden", "OQ.d2dx_runtime_gamesize"]} {"id": "council.wave4_gem_retag", "kind": "finding", "status": "noted", "desc": "Council wave-4 dissent (gem m4): the drop is the UI-RETAG. D2DX SurfaceIdTracker:88 retags world batches with minx>=640 as USER_INTERFACE when a panel is open; retagged verts get the UI orthographic projection (wrong for world coords) and render into the void = black. Fix he gave = hot-patch the minx>=640 Jcc in glide3x to fail ONLY during the floor draw call, then restore. NOTE: clau m6 REFUTES this - [640,960) is retagged too yet renders fine, so a rule that fires on visible geometry can't be the blackout rule.", "refs": ["council.wave4_consensus"]} {"id": "council.wave4_mandatory_measurement", "kind": "finding", "status": "noted", "desc": "Council wave-4: BOTH chat m5 and clau m6 demanded a PRE-PATCH measurement we never ran -- read D2DX's ACTUAL D3D11 world render-target width + viewport (RSGetViewports width; OMGetRenderTargets->GetDesc width/height) at the first Game-pass Draw, plus grSstWinOpen incoming args. chat's decision tree last branch: 'viewport 1280, RTV 1280+, constants 1280, still cutoff at 960 => your binary differs; next hook is ID3D11DeviceContext::Draw, inspect bound VS/PS and MRTs on the first missing floor batch' -- NOT SurfaceIdTracker.", "refs": ["OQ.d3d11_rt_width_unmeasured"]} {"id": "OQ.d3d11_rt_width_unmeasured", "kind": "openquestion", "status": "open", "desc": "DISAMBIGUATOR (council chat+clau demanded, never run): what is D2DX's ACTUAL D3D11 world render-target width + viewport, panel-open vs closed? Pairs with the panel-gated D2Glide submit probe to triangulate the stop point: (submit 640 + RT 1280)=>upstream D2Glide; (submit 1296 + RT 960)=>D2DX extent; (submit 1296 + RT 1280)=>wide-but-retagged (inspect MRTs). Build: hook ID3D11DeviceContext::Draw or read D2DX gameSize; or log grSstWinOpen incoming res arg (feature_d2dx already hooks it).", "refs": ["council.wave4_mandatory_measurement", "OQ.d2dx_runtime_gamesize", "OQ.panelopen_640_cull_vs_clamp"]} {"id": "reframe.one_cause_view_state", "kind": "finding", "status": "noted", "desc": "Doug reframe 2026-07-12: the dead zone, the panel-open camera SHIFT, and the world-vs-units DESYNC are ONE cause -- opening a panel CHANGES THE WORLD VIEW-STATE (offX=-320 + play-area narrowing). Clean target: render the world in the NO-PANEL view-state (no shift, full width) and composite the panel on top = ONE view-state (matches the ledger META-LESSON). Neutralize the change AT ITS SOURCE (the panel-open handler 0x6FB5AEC0 writing offX @0x6FB5AF7C), leaving the mode flag 0x6FBCC414 intact for culling (attempt A proved mode is load-bearing).", "refs": ["reframe.keep_shift_retired", "finding.shift_desync_is_half", "OQ.units_shift_left"]} {"id": "reframe.keep_shift_retired", "kind": "finding", "status": "noted", "desc": "RETIRED CONSTRAINT: 'keep the native -320 left-shift' (offX=0x6FBCC418, written @0x6FB5AF7C). Preserved through attempts A-H. Doug 2026-07-12 REVERSES it: wants ZERO shift on panel-open (world stays put, panel composites on top). 'both moves are inappropriate when opening the inventory if we have the world behind as we want.'", "refs": ["reframe.one_cause_view_state"]} {"id": "finding.shift_desync_is_half", "kind": "finding", "status": "observed", "desc": "Doug confirms 2026-07-12: panel-open, the WORLD shifts HALF as much as characters/items (units = ~2x world). Ledger theories (both unconfirmed): (a) multi-layer shift (floor vs wall/roof/units = separate draw fns), (b) double motion-smoothing (d2fps + D2DX both interpolate the camera move -> 2x on moving units, 1x on static terrain). Exactly-2x favors (b). MEASURE before patch: log offX(0x6FBCC418) + ctx+0x24 world-scroll + one unit screenpos, panel-open vs closed.", "refs": ["OQ.units_shift_left", "reframe.one_cause_view_state"]} {"id": "finding.clip_is_d2dx_drop_confirmed", "kind": "finding", "status": "confirmed", "desc": "CONFIRMED 2026-07-12 (v1.11.2 panel-gated probe, mode=1, GlideUnclamp=1): floor geometry REACHES the dead zone at the D2Glide->D2DX seam -- submit max 1264-1296, 338 verts in [960,1280) -- yet renders BLACK. The dead-zone black is a DROP at/after D2DX, NOT a D2Glide clip (GlideUnclamp already carries the submit to 1264). Independently reproduces council wave-4 (geometry crosses into D2DX in the dead zone, black). Next diagnostic = the council's demanded D2DX world-RT-width read (extent 960 vs UI-retag). SEPARATE from the world/objects SHIFT desync.", "refs": ["council.wave4_consensus", "council.wave4_gem_retag", "OQ.d3d11_rt_width_unmeasured", "finding.shift_desync_is_half"], "trust": "verified"} {"id": "finding.terrain_shift_is_offx_ctxL", "kind": "finding", "status": "confirmed", "desc": "CONFIRMED 2026-07-12 (v1.11.3 [SHIFT] snapshot, standing still): opening a side panel shifts the FLOOR/terrain by exactly -320 (1x = -DispW/4), and the WHOLE shift is offX(0x6FBCC418) 0->-320 driving ctx+0x04 0->-320. scrollX(ctx+0x24) is NOT touched by the panel (log changes there = the player walking). Terrain pan (ctxL - scrollX) moves -320. So the terrain-shift LEVER is offX->ctx+0x04. The objects-2x is a SEPARATE source: the shared tile projection is only 1x, so units (PASS2, a separate draw fn) pick up an EXTRA -320 downstream, NOT the camera/ctx. Which source (unit re-read of offX vs motion-smoothing) is unmeasured.", "refs": ["finding.shift_desync_is_half", "reframe.one_cause_view_state", "OQ.units_shift_left"], "trust": "verified"} {"id": "finding.offx_read_173_one_write", "kind": "finding", "status": "confirmed", "desc": "CONFIRMED 2026-07-12 (d2re xref 0x6FBCC418): offX is READ at 173 sites across D2Client, but WRITTEN once (0x6FB5AF7C, =-DispW/4=-320 on panel-open). So the surgical lever is the single write, not the 173 reads (blanket-patching reads = ledger attempt A = infeasible). CROSS-REF attempt A (held offX=0): un-shifted FLOOR + UNITS but NOT walls/roofs (a SEPARATE shift source) AND broke click-to-move (the hit-test reads offX). CONCLUSION: the panel shift is MULTI-SOURCE (offX for floor/units; a different global for walls/roofs) and HIT-TEST-COUPLED. Units read offX twice -> the 2x (theory a favored; not proven vs motion-smoothing). Naive offX=0 is OUT (already failed). The reframe goal (render world in no-panel view-state) needs an architecture decision, not a single patch.", "refs": ["finding.terrain_shift_is_offx_ctxL", "reframe.one_cause_view_state", "OQ.units_shift_left"], "trust": "verified"} {"id": "council.wave5_view_state_authorship", "kind": "finding", "status": "noted", "desc": "Council wave-5 (all 3 CONVERGE): kill the panel shift by AUTHORING a coherent NO-PANEL WORLD VIEW-STATE for the whole world-draw -- NOT per-value patching, NOT a mid-frame ctx swap (that's the C-G scheduling trap: 173 readers read at different times, no single safe instant). Two flavors: m1(chat)=post-hook the panel-transition routine (holds offX write 0x6FB5AF7C); after it runs, canonicalize the world-camera outputs (offX=0, wall/roof offset=0, ctx+0x04=0, ctx+0x0C=DispW) and HOLD persistent; keep ScreenOpenMode=1/2 (UI+input stay live). m2(gem)+m4(clau)=STATE-SPOOF: hook the world-draw, temporarily set the panel-state flags to 0 (lie 'no panel open'), call original (D2 naturally zeroes offX + wall offsets + hit-test), restore flags before the panel compositor 0x6FB739E0 -> ONE hook, hit-test solves itself, UI intact. Hit-test coherent BY CONSTRUCTION (render + mouse ray read the same authored state).", "refs": ["reframe.one_cause_view_state", "OQ.units_shift_left", "OQ.walls_shift_source", "council.wave5_d2dx_retag_is_the_black"]} {"id": "council.wave5_d2dx_retag_is_the_black", "kind": "finding", "status": "noted", "desc": "Council wave-5 CRITICAL LINK (m2 gem): the SHIFT fix and the dead-zone BLACK are the SAME downstream issue. Unshifting the world pushes valid geometry into x>=640; D2DX SurfaceIdTracker:88 retags world batches minx>=640 as USER_INTERFACE while a panel is open -> the UI orthographic projection drops those world verts -> black/corrupt right half. So authoring the no-panel view in D2Client is NECESSARY BUT NOT SUFFICIENT: we must ALSO defeat the D2DX minx>=640 retag during the world draw (runtime hot-patch the compare in glide3x, restore after). Defeating that retag IS the fix for the black.", "refs": ["finding.clip_is_d2dx_drop_confirmed", "council.wave4_gem_retag", "council.wave5_view_state_authorship"]} {"id": "OQ.walls_shift_source", "kind": "openquestion", "status": "closed", "desc": "BLOCKER (council wave-5 m1+m4): walls/roofs shift via a SEPARATE source, NOT offX (attempt A: offX=0 un-shifted floor+units but not walls). The authored no-panel view-state is INCOMPLETE until this source is named. Find it: read-breakpoint on the wall projection input during PASS2 (0x6FB3B110), or resolution-differential (vary DisplayWidth, scan for the value that tracks it AND encodes panel-open). Last unknown before the view-state-authorship patch. ==> TESTING (v1.12.0 attempt.I_noshift_lens): authoring ctxL=0 will show if walls read the ctx (un-shift) or a PASS2 recompute (stay shifted). ==> CLOSED (v1.12.0): the walls UN-SHIFTED with our ctxL=0 authoring -> the walls read the render context, NOT a separate source. Authoring the no-panel lens covers them.", "refs": ["council.wave5_view_state_authorship", "finding.offx_read_173_one_write"]} {"id": "struct.D2Client_RenderContext", "kind": "struct", "status": "confirmed", "author": "The Esoteric Path \u2014 verified vs the 1.13c binary", "module": "D2Client", "desc": "The world render context. Instance pointer = *0x6FBCC3C4. It IS the world view-state: the tile projection reads screenX = (+0x04) - (+0x24) + tileAbsX, screenY = tileAbsY - (+0x28) + (+0x08). A side panel writes +0x04 = offX = -320 (the shift) and narrows +0x0C to the play-area edge (the clip). See [[finding.terrain_shift_is_offx_ctxL]] and [[reframe.one_cause_view_state]].", "fields": [{"off": "+0x00", "name": "dirty", "type": "u32", "note": "geometry-dirty bit; |=1 forces mirror/cull rebuild for a wider window"}, {"off": "+0x04", "name": "draw_left", "type": "i32", "note": "draw-window L; equals offX (0 no-panel, -320 panel-open) -> the SHIFT"}, {"off": "+0x08", "name": "draw_top", "type": "i32", "note": "draw-window T"}, {"off": "+0x0C", "name": "draw_right", "type": "i32", "note": "draw-window R; iteration bound = 1280 no-panel, 960 panel-open -> the CLIP"}, {"off": "+0x10", "name": "draw_bottom", "type": "i32", "note": "draw-window B"}, {"off": "+0x24", "name": "scroll_x", "type": "i32", "note": "scroll origin X (camera); NOT touched by the panel"}, {"off": "+0x28", "name": "scroll_y", "type": "i32", "note": "scroll origin Y"}], "refs": ["finding.terrain_shift_is_offx_ctxL", "reframe.one_cause_view_state", "finding.offx_read_173_one_write"], "trust": "verified"} {"id": "struct.UnitAny", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/jankowskib/D2Ex2/master/D2Structs_113D.h", "desc": "The universal client-side game-entity struct; every player, monster, item, and object shares this layout, with a union selecting the type-specific data block.", "fields": [{"off": "0x00", "name": "dwType", "type": "DWORD", "note": ""}, {"off": "0x04", "name": "dwClassId", "type": "DWORD", "note": ""}, {"off": "0x08", "name": "pMemPool", "type": "void*", "note": ""}, {"off": "0x0C", "name": "dwUnitId", "type": "DWORD", "note": ""}, {"off": "0x10", "name": "dwMode", "type": "DWORD", "note": ""}, {"off": "0x14", "name": "pPlayerData", "type": "PlayerData*", "note": "union @0x14"}, {"off": "0x14", "name": "pItemData", "type": "ItemData*", "note": "union @0x14"}, {"off": "0x14", "name": "pMonsterData", "type": "MonsterData*", "note": "union @0x14"}, {"off": "0x14", "name": "pObjectData", "type": "ObjectData*", "note": "union @0x14"}, {"off": "0x18", "name": "dwAct", "type": "DWORD", "note": ""}, {"off": "0x1C", "name": "pAct", "type": "Act*", "note": ""}, {"off": "0x20", "name": "dwSeed[2]", "type": "DWORD", "note": ""}, {"off": "0x28", "name": "dwInitSeed", "type": "DWORD", "note": ""}, {"off": "0x2C", "name": "pPath", "type": "Path*", "note": "union @0x2C"}, {"off": "0x2C", "name": "pStaticPath", "type": "StaticPath*", "note": "union @0x2C"}, {"off": "0x30", "name": "_3[5]", "type": "DWORD", "note": ""}, {"off": "0x44", "name": "dwGfxFrame", "type": "DWORD", "note": ""}, {"off": "0x48", "name": "dwFrameRemain", "type": "DWORD", "note": ""}, {"off": "0x4C", "name": "wFrameRate", "type": "WORD", "note": ""}, {"off": "0x4E", "name": "_4", "type": "WORD", "note": ""}, {"off": "0x50", "name": "pAnimData", "type": "DWORD*", "note": ""}, {"off": "0x54", "name": "pGfxInfo", "type": "GfxInfo*", "note": ""}, {"off": "0x58", "name": "pGfxInfo2", "type": "GfxInfo*", "note": ""}, {"off": "0x5C", "name": "pStatsEx", "type": "StatListEx*", "note": ""}, {"off": "0x60", "name": "pInventory", "type": "Inventory*", "note": ""}, {"off": "0x64", "name": "pLight", "type": "Light*", "note": ""}, {"off": "0x68", "name": "dwLightRadious", "type": "DWORD", "note": ""}, {"off": "0x6C", "name": "nPalShiftIdx", "type": "WORD", "note": ""}, {"off": "0x6E", "name": "UpdateType", "type": "WORD", "note": ""}, {"off": "0x70", "name": "pUpdateUnit", "type": "UnitAny*", "note": ""}, {"off": "0x74", "name": "pQuestRecord", "type": "DWORD*", "note": ""}, {"off": "0x78", "name": "bSparkyChest", "type": "BYTE", "note": ""}, {"off": "0x79", "name": "_6a[3]", "type": "BYTE", "note": ""}, {"off": "0x7C", "name": "pTimerArgs", "type": "DWORD", "note": ""}, {"off": "0x80", "name": "dwSoundSync", "type": "DWORD", "note": ""}, {"off": "0x84", "name": "_7[2]", "type": "DWORD", "note": ""}, {"off": "0x8C", "name": "wX", "type": "WORD", "note": ""}, {"off": "0x8E", "name": "wY", "type": "WORD", "note": ""}, {"off": "0x90", "name": "pEvent", "type": "DWORD", "note": ""}, {"off": "0x94", "name": "dwOwnerType", "type": "DWORD", "note": ""}, {"off": "0x98", "name": "dwOwnerId", "type": "DWORD", "note": ""}, {"off": "0x9C", "name": "_8[2]", "type": "DWORD", "note": ""}, {"off": "0xA4", "name": "pHoverText", "type": "HoverText*", "note": ""}, {"off": "0xA8", "name": "pInfo", "type": "Info*", "note": ""}, {"off": "0xAC", "name": "ptCombat", "type": "void*", "note": ""}, {"off": "0xB0", "name": "dwLastHitClass", "type": "DWORD", "note": ""}, {"off": "0xB4", "name": "_9[4]", "type": "DWORD", "note": ""}, {"off": "0xC4", "name": "dwFlags", "type": "DWORD", "note": ""}, {"off": "0xC8", "name": "dwFlags2", "type": "DWORD", "note": ""}, {"off": "0xCC", "name": "_10[5]", "type": "DWORD", "note": ""}, {"off": "0xE0", "name": "pChangedNext", "type": "UnitAny*", "note": ""}, {"off": "0xE4", "name": "pRoomNext", "type": "UnitAny*", "note": "changed 14.12.11"}, {"off": "0xE8", "name": "pListNext", "type": "UnitAny*", "note": ""}, {"off": "0xEC", "name": "pMsgFirst", "type": "pMsg*", "note": ""}, {"off": "0xF0", "name": "pMsgLast", "type": "pMsg*", "note": ""}], "refs": []} {"id": "struct.PlayerData", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/jankowskib/D2Ex2/master/D2Structs_113D.h", "desc": "Per-player data block (name, quest flags, waypoints, assigned/switch skills, trade state) hung off UnitAny.pPlayerData; copied from the serverside layout.", "fields": [{"off": "0x00", "name": "szName[16]", "type": "char", "note": ""}, {"off": "0x10", "name": "QuestsFlags[3]", "type": "QuestFlags*", "note": ""}, {"off": "0x1C", "name": "pNormalWaypoint[3]", "type": "Waypoint*", "note": ""}, {"off": "0x28", "name": "ptAiGeneral", "type": "void*", "note": ""}, {"off": "0x2C", "name": "_1[2]", "type": "DWORD", "note": ""}, {"off": "0x34", "name": "KillCounter", "type": "WORD*", "note": "Monster"}, {"off": "0x38", "name": "_1b", "type": "DWORD", "note": ""}, {"off": "0x3C", "name": "_2[4]", "type": "DWORD", "note": "2[2] is merc related"}, {"off": "0x4C", "name": "dwTradeTick", "type": "DWORD", "note": "mby InactivityTime"}, {"off": "0x50", "name": "nTradeState", "type": "DWORD", "note": ""}, {"off": "0x54", "name": "_3", "type": "DWORD", "note": ""}, {"off": "0x58", "name": "dwAcceptTradeTick", "type": "DWORD", "note": ""}, {"off": "0x5C", "name": "pTrade", "type": "void*", "note": ""}, {"off": "0x60", "name": "_4[3]", "type": "DWORD", "note": ""}, {"off": "0x6C", "name": "dwBoughtItemId", "type": "DWORD", "note": ""}, {"off": "0x70", "name": "dwRightSkill", "type": "DWORD", "note": ""}, {"off": "0x74", "name": "dwLeftSkill", "type": "DWORD", "note": ""}, {"off": "0x78", "name": "dwRightSkillFlags", "type": "DWORD", "note": ""}, {"off": "0x7C", "name": "dwLeftSkillFlags", "type": "DWORD", "note": ""}, {"off": "0x80", "name": "dwSwitchRightSkill", "type": "DWORD", "note": ""}, {"off": "0x84", "name": "dwSwitchLeftSkill", "type": "DWORD", "note": ""}, {"off": "0x88", "name": "dwSwitchRightSkillFlags", "type": "DWORD", "note": ""}, {"off": "0x8C", "name": "dwSwitchLeftSkillFlags", "type": "DWORD", "note": ""}, {"off": "0x90", "name": "_5[3]", "type": "DWORD", "note": ""}, {"off": "0x9C", "name": "pClientData", "type": "ClientData*", "note": ""}, {"off": "0x100", "name": "_6[50]", "type": "DWORD", "note": ""}, {"off": "0x168", "name": "GameFrame", "type": "DWORD", "note": ""}], "refs": []} {"id": "struct.MonsterData", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/jankowskib/D2Ex2/master/D2Structs_113D.h", "desc": "Per-monster data block (txt record, gfx components, name seed, unique/champion/minion bit-flags, enchantments, AI pointer, name) hung off UnitAny.pMonsterData.", "fields": [{"off": "0x00", "name": "pMonStatsTxt", "type": "MonStatsTxt*", "note": ""}, {"off": "0x04", "name": "Components[16]", "type": "BYTE", "note": ""}, {"off": "0x14", "name": "NameSeed", "type": "WORD", "note": ""}, {"off": "0x16", "name": "(anonymous bitfield)", "type": "BYTE : 1 (x8)", "note": "fOther, fSuperUniq, fChampion, fUnique, fMinion, fPossesed, fGhostly, fMultishot (each 1 bit)"}, {"off": "0x17", "name": "dwLastMode", "type": "BYTE", "note": ""}, {"off": "0x18", "name": "dwDuriel", "type": "DWORD", "note": ""}, {"off": "0x1C", "name": "anEnchants[9]", "type": "BYTE", "note": ""}, {"off": "0x25", "name": "_1", "type": "BYTE", "note": ""}, {"off": "0x26", "name": "wUniqueNo", "type": "WORD", "note": ""}, {"off": "0x28", "name": "pAiGeneral", "type": "AiGeneral*", "note": ""}, {"off": "0x2C", "name": "wName[28]", "type": "wchar_t*", "note": ""}], "refs": []} {"id": "struct.ObjectData", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/jankowskib/D2Ex2/master/D2Structs_113D.h", "desc": "Per-object data block (object txt record, interaction type, owner name) hung off UnitAny.pObjectData.", "fields": [{"off": "0x00", "name": "pObjectTxt", "type": "ObjectTxt*", "note": ""}, {"off": "0x04", "name": "InteractType", "type": "BYTE", "note": ""}, {"off": "0x05", "name": "_1[3]", "type": "BYTE", "note": ""}, {"off": "0x08", "name": "_2[8]", "type": "DWORD", "note": ""}, {"off": "0x28", "name": "szOwner[16]", "type": "char", "note": ""}], "refs": []} {"id": "struct.ItemData", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/jankowskib/D2Ex2/master/D2Structs_113D.h", "desc": "Per-item data block (quality, seeds, owner, flags, prefixes/suffixes, body & inventory location, socket linkage) hung off UnitAny.pItemData.", "fields": [{"off": "0x00", "name": "QualityNo", "type": "DWORD", "note": ""}, {"off": "0x04", "name": "LowSeed", "type": "DWORD", "note": ""}, {"off": "0x08", "name": "HighSeed", "type": "DWORD", "note": ""}, {"off": "0x0C", "name": "OwnerID", "type": "DWORD", "note": ""}, {"off": "0x10", "name": "InitSeed", "type": "DWORD", "note": ""}, {"off": "0x14", "name": "CommandFlags", "type": "DWORD", "note": ""}, {"off": "0x18", "name": "ItemFlags", "type": "DWORD", "note": ""}, {"off": "0x1C", "name": "_1[2]", "type": "DWORD", "note": ""}, {"off": "0x24", "name": "ActionStamp", "type": "DWORD", "note": ""}, {"off": "0x28", "name": "FileIndex", "type": "DWORD", "note": ""}, {"off": "0x2C", "name": "ItemLevel", "type": "DWORD", "note": ""}, {"off": "0x30", "name": "ItemFormat", "type": "WORD", "note": ""}, {"off": "0x32", "name": "RarePrefix", "type": "WORD", "note": ""}, {"off": "0x34", "name": "RareSutfix", "type": "WORD", "note": ""}, {"off": "0x36", "name": "AutoPrefix", "type": "WORD", "note": ""}, {"off": "0x38", "name": "MagicPrefix[3]", "type": "WORD", "note": ""}, {"off": "0x3E", "name": "MagicSutfix[3]", "type": "WORD", "note": ""}, {"off": "0x44", "name": "BodyLoc", "type": "BYTE", "note": "location on body = xpos of item (only if on body) (spread)"}, {"off": "0x45", "name": "InvPage", "type": "BYTE", "note": "0 = inventory, 3 = cube, 4 = stash (spread)"}, {"off": "0x46", "name": "_2[2]", "type": "BYTE", "note": ""}, {"off": "0x48", "name": "EarLvl", "type": "BYTE", "note": ""}, {"off": "0x49", "name": "InvGfxIdx", "type": "BYTE", "note": ""}, {"off": "0x4A", "name": "szPlayerName[16]", "type": "char", "note": ""}, {"off": "0x5A", "name": "_3[2]", "type": "BYTE", "note": ""}, {"off": "0x5C", "name": "pNodeInv", "type": "Inventory*", "note": ""}, {"off": "0x60", "name": "_4", "type": "DWORD", "note": ""}, {"off": "0x64", "name": "pNextItem", "type": "UnitAny*", "note": ""}, {"off": "0x68", "name": "NodePos", "type": "BYTE", "note": ""}, {"off": "0x69", "name": "NodePosOther", "type": "BYTE", "note": ""}], "refs": []} {"id": "struct.Path", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/jankowskib/D2Ex2/master/D2Structs_113D.h", "desc": "Movement/position path for an active (moving) unit: current and target coordinates, owning rooms, collision flags, path type, target unit, and facing direction.", "fields": [{"off": "0x00", "name": "xOffset", "type": "short", "note": ""}, {"off": "0x02", "name": "xPos", "type": "short", "note": ""}, {"off": "0x04", "name": "yOffset", "type": "short", "note": ""}, {"off": "0x06", "name": "yPos", "type": "short", "note": ""}, {"off": "0x08", "name": "xUnknown", "type": "DWORD", "note": "16 * (wInitX - wInitY) <- Mby AutomapX"}, {"off": "0x0C", "name": "yUnknown", "type": "DWORD", "note": "8 * (wInitX + wInitY + 1) <- Mby AutoampY"}, {"off": "0x10", "name": "xTarget", "type": "short", "note": ""}, {"off": "0x12", "name": "yTarget", "type": "short", "note": ""}, {"off": "0x14", "name": "_2[2]", "type": "DWORD", "note": ""}, {"off": "0x1C", "name": "pRoom1", "type": "Room1*", "note": ""}, {"off": "0x20", "name": "pRoomUnk", "type": "Room1*", "note": ""}, {"off": "0x24", "name": "_3[3]", "type": "DWORD", "note": ""}, {"off": "0x30", "name": "pUnit", "type": "UnitAny*", "note": ""}, {"off": "0x34", "name": "dwFlags", "type": "DWORD", "note": "0x40000 -> PATH_MISSILE_MASK"}, {"off": "0x38", "name": "_4", "type": "DWORD", "note": ""}, {"off": "0x3C", "name": "dwPathType", "type": "DWORD", "note": ""}, {"off": "0x40", "name": "dwPrevPathType", "type": "DWORD", "note": ""}, {"off": "0x44", "name": "dwUnitSize", "type": "DWORD", "note": ""}, {"off": "0x48", "name": "_5[2]", "type": "DWORD", "note": ""}, {"off": "0x50", "name": "dwCollisionFlag", "type": "DWORD", "note": "0x1804 <- bFlying, 0x3401 <- bOpenDoors, 0x3C01 <- Cannot Open Doors, 0x804 <- Ghost, 0x1C09 <- Player"}, {"off": "0x54", "name": "_5d", "type": "DWORD", "note": ""}, {"off": "0x58", "name": "pTargetUnit", "type": "UnitAny*", "note": ""}, {"off": "0x5C", "name": "dwTargetType", "type": "DWORD", "note": ""}, {"off": "0x60", "name": "dwTargetId", "type": "DWORD", "note": ""}, {"off": "0x64", "name": "bDirection", "type": "BYTE", "note": ""}], "refs": []} {"id": "struct.StaticPath", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/jankowskib/D2Ex2/master/D2Structs_113D.h", "desc": "Simplified position record (size 0x20) for units that do not move (items/objects): owning room plus offset and grid position.", "fields": [{"off": "0x00", "name": "pRoom1", "type": "Room1*", "note": ""}, {"off": "0x04", "name": "xOffset", "type": "DWORD", "note": ""}, {"off": "0x08", "name": "yOffset", "type": "DWORD", "note": ""}, {"off": "0x0C", "name": "xPos", "type": "DWORD", "note": ""}, {"off": "0x10", "name": "yPos", "type": "DWORD", "note": ""}, {"off": "0x14", "name": "_1[2]", "type": "DWORD", "note": ""}, {"off": "0x1C", "name": "dwFlags", "type": "DWORD", "note": ""}], "refs": []} {"id": "struct.Info", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/jankowskib/D2Ex2/master/D2Structs_113D.h", "desc": "Skill container hung off UnitAny.pInfo: mem pool plus pointers to the first, left-hand, and right-hand active skills.", "fields": [{"off": "0x00", "name": "pMemPool", "type": "DWORD*", "note": ""}, {"off": "0x04", "name": "pFirstSkill", "type": "Skill*", "note": ""}, {"off": "0x08", "name": "pLeftSkill", "type": "Skill*", "note": ""}, {"off": "0x0C", "name": "pRightSkill", "type": "Skill*", "note": ""}], "refs": []} {"id": "struct.Skill", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/jankowskib/D2Ex2/master/D2Structs_113D.h", "desc": "A single skill entry in a unit's skill linked list: txt record, next-link, mode, level, and flags.", "fields": [{"off": "0x00", "name": "pSkillsTxt", "type": "SkillsTxt*", "note": ""}, {"off": "0x04", "name": "pNextSkill", "type": "Skill*", "note": ""}, {"off": "0x08", "name": "SkillMode", "type": "DWORD", "note": ""}, {"off": "0x0C", "name": "_1[7]", "type": "DWORD", "note": ""}, {"off": "0x28", "name": "dwSkillLevel", "type": "DWORD", "note": ""}, {"off": "0x2C", "name": "_2[2]", "type": "DWORD", "note": ""}, {"off": "0x30", "name": "dwFlags", "type": "DWORD", "note": ""}], "refs": []} {"id": "struct.SkillInfo", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/noah-/d2bs/master/D2Structs.h", "desc": "Skill identifier record referenced by Skill.pSkillInfo; holds the skill id. NOTE: absent from D2Structs_113D.h (which uses SkillsTxt* directly) \u2014 this definition comes only from the d2bs D2Structs.h.", "fields": [{"off": "0x00", "name": "wSkillId", "type": "WORD", "note": ""}], "refs": []} {"id": "struct.Room1", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/jankowskib/D2Ex2/master/D2Structs_113D.h", "desc": "Active/in-memory room node holding collision map, units, and nearby-room links for a level.", "fields": [{"off": "0x00", "name": "pRoomsNear", "type": "Room1**", "note": "pptVisibleRooms"}, {"off": "0x04", "name": "_1", "type": "DWORD", "note": ""}, {"off": "0x08", "name": "_1s", "type": "void*", "note": ""}, {"off": "0x0C", "name": "_1b", "type": "DWORD", "note": ""}, {"off": "0x10", "name": "pRoom2", "type": "Room2*", "note": ""}, {"off": "0x14", "name": "_2[2]", "type": "DWORD", "note": ""}, {"off": "0x1C", "name": "pUnitChanged", "type": "UnitAny**", "note": ""}, {"off": "0x20", "name": "Coll", "type": "CollMap*", "note": ""}, {"off": "0x24", "name": "dwRoomsNear", "type": "DWORD", "note": "dwVisibleRooms"}, {"off": "0x28", "name": "nPlayerUnits", "type": "DWORD", "note": ""}, {"off": "0x2C", "name": "pAct", "type": "Act*", "note": ""}, {"off": "0x30", "name": "_4", "type": "DWORD", "note": ""}, {"off": "0x34", "name": "nUnknown", "type": "DWORD", "note": ""}, {"off": "0x38", "name": "_5[4]", "type": "DWORD", "note": ""}, {"off": "0x48", "name": "pClients", "type": "ClientData**", "note": ""}, {"off": "0x4C", "name": "hCoords", "type": "RoomCoords", "note": ""}, {"off": "0x6C", "name": "hSeed", "type": "D2Seed", "note": ""}, {"off": "0x74", "name": "pUnitFirst", "type": "UnitAny*", "note": ""}, {"off": "0x78", "name": "nNumClients", "type": "DWORD", "note": ""}, {"off": "0x7C", "name": "pRoomNext", "type": "Room1*", "note": ""}], "refs": []} {"id": "struct.Room2", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/jankowskib/D2Ex2/master/D2Structs_113D.h", "desc": "Static/preset room descriptor (DRLG layout) linking to its Room1, level, tiles, and preset units.", "fields": [{"off": "0x00", "name": "_1[2]", "type": "DWORD", "note": ""}, {"off": "0x08", "name": "pRoom2Near", "type": "Room2**", "note": ""}, {"off": "0x0C", "name": "_2[2]", "type": "DWORD", "note": ""}, {"off": "0x14", "name": "hSeed", "type": "D2Seed", "note": ""}, {"off": "0x1C", "name": "_2b", "type": "DWORD", "note": ""}, {"off": "0x20", "name": "pType2Info", "type": "struct { DWORD dwRoomNumber; DWORD* _1; DWORD* pdwSubNumber; }*", "note": "inline anon struct: dwRoomNumber //0x00, _1 //0x04, pdwSubNumber //0x08. points to 0x70 struct if dwPresetType == 1, 0xF8 struct if == 2"}, {"off": "0x24", "name": "pRoom2Next", "type": "Room2*", "note": ""}, {"off": "0x28", "name": "dwRoomFlags", "type": "DWORD", "note": ""}, {"off": "0x2C", "name": "dwRoomsNear", "type": "DWORD", "note": ""}, {"off": "0x30", "name": "pRoom1", "type": "Room1*", "note": ""}, {"off": "0x34", "name": "dwPosX", "type": "DWORD", "note": ""}, {"off": "0x38", "name": "dwPosY", "type": "DWORD", "note": ""}, {"off": "0x3C", "name": "dwSizeX", "type": "DWORD", "note": ""}, {"off": "0x40", "name": "dwSizeY", "type": "DWORD", "note": ""}, {"off": "0x44", "name": "_3", "type": "DWORD", "note": ""}, {"off": "0x48", "name": "dwPresetType", "type": "DWORD", "note": ""}, {"off": "0x4C", "name": "pRoomTiles", "type": "RoomTile*", "note": ""}, {"off": "0x50", "name": "_4[2]", "type": "DWORD", "note": ""}, {"off": "0x58", "name": "pLevel", "type": "Level*", "note": ""}, {"off": "0x5C", "name": "pPreset", "type": "PresetUnit*", "note": ""}], "refs": []} {"id": "struct.Level", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/jankowskib/D2Ex2/master/D2Structs_113D.h", "desc": "A single DRLG level (map area) with its rooms, size/position, seed, presets, and warp/room-center coordinates. sizeof = 0x230.", "fields": [{"off": "0x00", "name": "dwDrlgType", "type": "DWORD", "note": "1 - maze, 2 - preset, 3 - wilderness"}, {"off": "0x04", "name": "dwLevelFlags", "type": "DWORD", "note": ""}, {"off": "0x08", "name": "_1[2]", "type": "DWORD", "note": ""}, {"off": "0x10", "name": "pRoom2First", "type": "Room2*", "note": ""}, {"off": "0x14", "name": "(anonymous union)", "type": "union { LvlMazeTxt* pMazeTxt; PresetData* pPreset; WildernessData* pWilderness; }", "note": "pMazeTxt for dwDrlgType==1 (RANDOM MAZE); pPreset for dwDrlgType==2 (PRESET MAP); pWilderness for dwDrlgType==3 (RANDOM AREA WITH PRESET SIZE)"}, {"off": "0x18", "name": "_2", "type": "DWORD", "note": ""}, {"off": "0x1C", "name": "dwPosX", "type": "DWORD", "note": ""}, {"off": "0x20", "name": "dwPosY", "type": "DWORD", "note": ""}, {"off": "0x24", "name": "dwSizeX", "type": "DWORD", "note": ""}, {"off": "0x28", "name": "dwSizeY", "type": "DWORD", "note": ""}, {"off": "0x2C", "name": "_3[96]", "type": "DWORD", "note": ""}, {"off": "0x1AC", "name": "pNextLevel", "type": "Level*", "note": ""}, {"off": "0x1B0", "name": "_4", "type": "DWORD", "note": ""}, {"off": "0x1B4", "name": "pMisc", "type": "ActMisc*", "note": ""}, {"off": "0x1B8", "name": "_5[2]", "type": "DWORD", "note": ""}, {"off": "0x1C0", "name": "dwLevelType", "type": "DWORD", "note": ""}, {"off": "0x1C4", "name": "hSeed", "type": "D2Seed", "note": ""}, {"off": "0x1CC", "name": "pLevelPresets", "type": "LevelPreset*", "note": ""}, {"off": "0x1D0", "name": "dwLevelNo", "type": "DWORD", "note": ""}, {"off": "0x1D4", "name": "_6[3]", "type": "DWORD", "note": ""}, {"off": "0x1E0", "name": "(anonymous union)", "type": "union { DWORD RoomCenterX[9]; DWORD WarpX[9]; }", "note": ""}, {"off": "0x204", "name": "(anonymous union)", "type": "union { DWORD RoomCenterY[9]; DWORD WarpY[9]; }", "note": ""}, {"off": "0x228", "name": "dwRoomEntries", "type": "DWORD", "note": ""}, {"off": "0x22C", "name": "_7", "type": "DWORD", "note": ""}], "refs": []} {"id": "struct.Act", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/jankowskib/D2Ex2/master/D2Structs_113D.h", "desc": "Per-act runtime container holding the act's environment, town level, map seed, root room, and DRLG misc pointer.", "fields": [{"off": "0x00", "name": "_1a", "type": "DWORD", "note": ""}, {"off": "0x04", "name": "pEnviroment", "type": "ActEnvironment*", "note": ""}, {"off": "0x08", "name": "dwTownLvl", "type": "DWORD", "note": ""}, {"off": "0x0C", "name": "dwMapSeed", "type": "DWORD", "note": ""}, {"off": "0x10", "name": "pRoom1", "type": "Room1*", "note": ""}, {"off": "0x14", "name": "dwAct", "type": "DWORD", "note": ""}, {"off": "0x18", "name": "hTile[12]", "type": "DWORD", "note": "not sure, some inline struct of 0x30 size seems fit"}, {"off": "0x48", "name": "pMisc", "type": "ActMisc*", "note": ""}, {"off": "0x4C", "name": "_4", "type": "DWORD", "note": ""}, {"off": "0x50", "name": "_5", "type": "DWORD", "note": ""}, {"off": "0x54", "name": "_6", "type": "DWORD", "note": ""}, {"off": "0x58", "name": "_7", "type": "DWORD", "note": ""}, {"off": "0x5C", "name": "pMemPool", "type": "void*", "note": ""}], "refs": []} {"id": "struct.ActMisc", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/jankowskib/D2Ex2/master/D2Structs_113D.h", "desc": "DRLG-level misc/generation state for an act (aka Drlg): seeds, tile pointers, callbacks, level list, and back-pointer to Act. sizeof(0x48C).", "fields": [{"off": "0x00", "name": "hSeed", "type": "D2Seed", "note": ""}, {"off": "0x08", "name": "_1", "type": "DWORD", "note": ""}, {"off": "0x0C", "name": "pTile", "type": "DWORD*", "note": ""}, {"off": "0x10", "name": "_1g[15]", "type": "DWORD", "note": ""}, {"off": "0x4c", "name": "pfnCallBack", "type": "DWORD", "note": ""}, {"off": "0x50", "name": "_1a[16]", "type": "DWORD", "note": ""}, {"off": "0x90", "name": "pVis", "type": "DrlgVis*", "note": ""}, {"off": "0x94", "name": "dwStaffTombLevel", "type": "DWORD", "note": ""}, {"off": "0x98", "name": "_2a", "type": "DWORD", "note": ""}, {"off": "0x9C", "name": "pGame", "type": "Game*", "note": ""}, {"off": "0xA0", "name": "_2[236]", "type": "DWORD", "note": ""}, {"off": "0x450", "name": "nDiffLvl", "type": "DWORD", "note": ""}, {"off": "0x454", "name": "fnCallback", "type": "DWORD*", "note": ""}, {"off": "0x458", "name": "InitSeed", "type": "DWORD", "note": ""}, {"off": "0x45C", "name": "_2d[4]", "type": "DWORD", "note": ""}, {"off": "0x46C", "name": "pAct", "type": "Act*", "note": ""}, {"off": "0x470", "name": "_3[2]", "type": "DWORD", "note": ""}, {"off": "0x478", "name": "pMemPool", "type": "void*", "note": "D2PoolManager*"}, {"off": "0x47C", "name": "pLevelFirst", "type": "Level*", "note": ""}, {"off": "0x480", "name": "nAct", "type": "DWORD", "note": ""}, {"off": "0x484", "name": "_5", "type": "DWORD", "note": "Tomb Levels Related 66 + rand(7)"}, {"off": "0x488", "name": "fnCallback2", "type": "DWORD*", "note": ""}], "refs": []} {"id": "struct.PresetUnit", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/jankowskib/D2Ex2/master/D2Structs_113D.h", "desc": "A preplaced (preset) unit within a Room2 \u2014 class/type id and tile position, linked as a list.", "fields": [{"off": "0x00", "name": "_1", "type": "DWORD", "note": ""}, {"off": "0x04", "name": "dwClassId", "type": "DWORD", "note": ""}, {"off": "0x08", "name": "dwPosX", "type": "DWORD", "note": ""}, {"off": "0x0C", "name": "pPresetNext", "type": "PresetUnit*", "note": ""}, {"off": "0x10", "name": "_3", "type": "DWORD", "note": ""}, {"off": "0x14", "name": "dwType", "type": "DWORD", "note": ""}, {"off": "0x18", "name": "dwPosY", "type": "DWORD", "note": ""}], "refs": []} {"id": "struct.RoomTile", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/jankowskib/D2Ex2/master/D2Structs_113D.h", "desc": "A tile linking a Room2 to a neighboring room (warp/connection), stored as a linked list.", "fields": [{"off": "0x00", "name": "pRoom2", "type": "Room2*", "note": ""}, {"off": "0x04", "name": "pNext", "type": "RoomTile*", "note": ""}, {"off": "0x08", "name": "_2[2]", "type": "DWORD", "note": ""}, {"off": "0x10", "name": "nNum", "type": "DWORD*", "note": ""}], "refs": []} {"id": "struct.Stat", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/jankowskib/D2Ex2/master/D2Structs_113D.h", "desc": "A single stat entry: sub-index, stat index, and value.", "fields": [{"off": "0x00", "name": "wSubIndex", "type": "WORD", "note": ""}, {"off": "0x02", "name": "wStatIndex", "type": "WORD", "note": ""}, {"off": "0x04", "name": "dwStatValue", "type": "DWORD", "note": ""}], "refs": []} {"id": "struct.StatEx", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/jankowskib/D2Ex2/master/D2Structs_113D.h", "desc": "A stat vector/array container: pointer to a Stat array plus counts (size 0x8).", "fields": [{"off": "0x00", "name": "pStat", "type": "Stat*", "note": "An Array[wStatCount]"}, {"off": "0x04", "name": "wStatCount", "type": "WORD", "note": ""}, {"off": "0x06", "name": "wnBitSize", "type": "WORD", "note": ""}], "refs": []} {"id": "struct.StatList", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/jankowskib/D2Ex2/master/D2Structs_113D.h", "desc": "A node in a unit's linked list of stats (size 0x40).", "fields": [{"off": "0x00", "name": "pMemPool", "type": "void*", "note": ""}, {"off": "0x04", "name": "pUnit", "type": "UnitAny*", "note": ""}, {"off": "0x08", "name": "dwOwnerType", "type": "DWORD", "note": ""}, {"off": "0x0C", "name": "dwOwnerId", "type": "DWORD", "note": ""}, {"off": "0x10", "name": "dwFlags", "type": "DWORD", "note": ""}, {"off": "0x14", "name": "dwStateNo", "type": "DWORD", "note": ""}, {"off": "0x18", "name": "ExpireFrame", "type": "DWORD", "note": ""}, {"off": "0x1C", "name": "SkillNo", "type": "DWORD", "note": ""}, {"off": "0x20", "name": "sLvl", "type": "DWORD", "note": ""}, {"off": "0x24", "name": "Stats", "type": "StatEx", "note": ""}, {"off": "0x2C", "name": "pPrevLink", "type": "StatList*", "note": ""}, {"off": "0x30", "name": "pNextLink", "type": "StatList*", "note": ""}, {"off": "0x34", "name": "pPrev", "type": "StatList*", "note": ""}, {"off": "0x38", "name": "fpStatRemove", "type": "void*", "note": ""}, {"off": "0x3C", "name": "pNext", "type": "StatList*", "note": ""}], "refs": []} {"id": "struct.StatListEx", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/jankowskib/D2Ex2/master/D2Structs_113D.h", "desc": "Extended stat list container tracking base/full/mod stats for a unit or item (size 0x64).", "fields": [{"off": "0x00", "name": "pMemPool", "type": "DWORD", "note": ""}, {"off": "0x04", "name": "_1", "type": "DWORD", "note": ""}, {"off": "0x08", "name": "dwOwnerType", "type": "DWORD", "note": ""}, {"off": "0x0C", "name": "dwOwnerId", "type": "DWORD", "note": ""}, {"off": "0x10", "name": "dwListFlags", "type": "DWORD", "note": ""}, {"off": "0x14", "name": "_2[4]", "type": "DWORD", "note": ""}, {"off": "0x24", "name": "BaseStats", "type": "StatEx", "note": ""}, {"off": "0x2C", "name": "pLastList", "type": "StatList*", "note": "pointer to the last pStatList of the StatListEx owner (aka item owner in case list ex belongs to item)"}, {"off": "0x30", "name": "_3", "type": "DWORD", "note": ""}, {"off": "0x34", "name": "pListEx", "type": "StatListEx*", "note": "pStatListEx - pointer to owner StatListEx (if this one is owned by a item, this points to the item owners list)"}, {"off": "0x38", "name": "pNextListEx", "type": "StatListEx*", "note": ""}, {"off": "0x3C", "name": "pMyLastList", "type": "StatList*", "note": ""}, {"off": "0x40", "name": "pMyStats", "type": "StatList*", "note": ""}, {"off": "0x44", "name": "pOwner", "type": "UnitAny*", "note": ""}, {"off": "0x48", "name": "FullStats", "type": "StatEx", "note": ""}, {"off": "0x50", "name": "ModStats", "type": "StatEx", "note": ""}, {"off": "0x58", "name": "StatFlags", "type": "BYTE*", "note": "pt to an array"}, {"off": "0x5C", "name": "fpCallBack", "type": "void*", "note": ""}, {"off": "0x60", "name": "ptGame", "type": "Game*", "note": ""}], "refs": []} {"id": "struct.Inventory", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/jankowskib/D2Ex2/master/D2Structs_113D.h", "desc": "A unit's inventory: item linked list plus cursor/owner/count data.", "fields": [{"off": "0x00", "name": "dwSignature", "type": "DWORD", "note": ""}, {"off": "0x04", "name": "pMemPool", "type": "BYTE*", "note": ""}, {"off": "0x08", "name": "pOwner", "type": "UnitAny*", "note": ""}, {"off": "0x0C", "name": "pFirstItem", "type": "UnitAny*", "note": ""}, {"off": "0x10", "name": "pLastItem", "type": "UnitAny*", "note": ""}, {"off": "0x14", "name": "_1[2]", "type": "DWORD", "note": ""}, {"off": "0x1C", "name": "dwLeftItemUid", "type": "DWORD", "note": ""}, {"off": "0x20", "name": "pCursorItem", "type": "UnitAny*", "note": ""}, {"off": "0x24", "name": "dwOwnerId", "type": "DWORD", "note": ""}, {"off": "0x28", "name": "dwItemCount", "type": "DWORD", "note": ""}, {"off": "0x2C", "name": "_2[4]", "type": "DWORD", "note": ""}, {"off": "0x3C", "name": "CorpseNumber", "type": "DWORD", "note": ""}], "refs": []} {"id": "struct.InventoryLayout", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/noah-/d2bs/master/D2Structs.h", "desc": "Layout/geometry of an inventory grid panel (slot sizes and screen bounds). Not present in D2Structs_113D.h; taken from d2bs D2Structs.h, which has no offset comments.", "fields": [{"off": "", "name": "SlotWidth", "type": "BYTE", "note": ""}, {"off": "", "name": "SlotHeight", "type": "BYTE", "note": ""}, {"off": "", "name": "unk1", "type": "BYTE", "note": ""}, {"off": "", "name": "unk2", "type": "BYTE", "note": ""}, {"off": "", "name": "Left", "type": "DWORD", "note": ""}, {"off": "", "name": "Right", "type": "DWORD", "note": ""}, {"off": "", "name": "Top", "type": "DWORD", "note": ""}, {"off": "", "name": "Bottom", "type": "DWORD", "note": ""}, {"off": "", "name": "SlotPixelWidth", "type": "BYTE", "note": ""}, {"off": "", "name": "SlotPixelHeight", "type": "BYTE", "note": ""}], "refs": []} {"id": "struct.GfxCell", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/jankowskib/D2Ex2/master/D2Structs_113D.h", "desc": "A single frame/cell of a DC6/DCC sprite graphic (dimensions, draw offsets, pixel data length).", "fields": [{"off": "0x00", "name": "flags", "type": "DWORD", "note": ""}, {"off": "0x04", "name": "width", "type": "DWORD", "note": ""}, {"off": "0x08", "name": "height", "type": "DWORD", "note": ""}, {"off": "0x0C", "name": "xoffs", "type": "int", "note": ""}, {"off": "0x10", "name": "yoffs", "type": "int", "note": ""}, {"off": "0x14", "name": "_2", "type": "DWORD", "note": ""}, {"off": "0x18", "name": "lpParent", "type": "DWORD", "note": ""}, {"off": "0x1C", "name": "length", "type": "DWORD", "note": ""}, {"off": "0x20", "name": "cols", "type": "BYTE", "note": ""}], "refs": []} {"id": "struct.CellContext", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/jankowskib/D2Ex2/master/D2Structs_113D.h", "desc": "Rendering context binding a unit/component to its cell file and current graphics cell and facing direction (size 0x48).", "fields": [{"off": "0x00", "name": "nCellNo", "type": "DWORD", "note": ""}, {"off": "0x04", "name": "_0a", "type": "DWORD", "note": ""}, {"off": "0x08", "name": "dwUnit", "type": "DWORD", "note": ""}, {"off": "0x0C", "name": "dwClass", "type": "DWORD", "note": ""}, {"off": "0x10", "name": "dwMode", "type": "DWORD", "note": ""}, {"off": "0x14", "name": "_3", "type": "DWORD", "note": ""}, {"off": "0x18", "name": "_4", "type": "DWORD", "note": ""}, {"off": "0x1C", "name": "_5", "type": "BYTE", "note": ""}, {"off": "0x1D", "name": "_5a", "type": "BYTE", "note": ""}, {"off": "0x1E", "name": "_6", "type": "WORD", "note": ""}, {"off": "0x20", "name": "_7", "type": "DWORD", "note": ""}, {"off": "0x24", "name": "_8", "type": "DWORD", "note": ""}, {"off": "0x28", "name": "_9", "type": "DWORD", "note": ""}, {"off": "0x2C", "name": "szName", "type": "char*", "note": ""}, {"off": "0x30", "name": "_11", "type": "DWORD", "note": ""}, {"off": "0x34", "name": "pCellFile", "type": "CellFile*", "note": "also pCellInit"}, {"off": "0x38", "name": "_12", "type": "DWORD", "note": ""}, {"off": "0x3C", "name": "pGfxCells", "type": "GfxCell*", "note": ""}, {"off": "0x40", "name": "direction", "type": "DWORD", "note": ""}, {"off": "0x44", "name": "_14", "type": "DWORD", "note": ""}], "refs": []} {"id": "struct.GfxInfo", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/jankowskib/D2Ex2/master/D2Structs_113D.h", "desc": "Graphics draw-info block holding the draw-offset table pointer and palette-shift index for a sprite.", "fields": [{"off": "0x00", "name": "_1", "type": "DWORD", "note": ""}, {"off": "0x04", "name": "_2", "type": "DWORD", "note": ""}, {"off": "0x08", "name": "_3", "type": "DWORD", "note": ""}, {"off": "0x0C", "name": "_4", "type": "DWORD", "note": ""}, {"off": "0x10", "name": "_5", "type": "DWORD", "note": ""}, {"off": "0x14", "name": "_6", "type": "DWORD", "note": ""}, {"off": "0x18", "name": "_7", "type": "DWORD", "note": ""}, {"off": "0x1C", "name": "_8", "type": "DWORD", "note": ""}, {"off": "0x20", "name": "_9", "type": "DWORD", "note": ""}, {"off": "0x24", "name": "_10", "type": "DWORD", "note": ""}, {"off": "0x28", "name": "_11", "type": "DWORD", "note": ""}, {"off": "0x2C", "name": "_12", "type": "DWORD", "note": ""}, {"off": "0x30", "name": "pGfxDrawOffsets", "type": "GfxDrawOffset*", "note": ""}, {"off": "0x34", "name": "_13", "type": "DWORD", "note": ""}, {"off": "0x38", "name": "nPalShiftIdx", "type": "DWORD", "note": ""}], "refs": []} {"id": "struct.Light", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/noah-/d2bs/master/D2Structs.h", "desc": "A dynamic light source in the game world (type, static lightmap validity flag and map pointer). Only a forward declaration exists in 113D, so the d2bs body is used.", "fields": [{"off": "0x00", "name": "_1[3]", "type": "DWORD", "note": ""}, {"off": "0x0C", "name": "dwType", "type": "DWORD", "note": ""}, {"off": "0x10", "name": "_2[7]", "type": "DWORD", "note": ""}, {"off": "0x2C", "name": "dwStaticValid", "type": "DWORD", "note": ""}, {"off": "0x30", "name": "pnStaticMap", "type": "int*", "note": ""}], "refs": []} {"id": "struct.AutoMapLayer", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/jankowskib/D2Ex2/master/D2Structs_113D.h", "desc": "A layer of the automap holding linked lists of floor/wall/object/extra cells (sizeof = 0x1C). Verbatim source spelling is AutoMapLayer.", "fields": [{"off": "0x00", "name": "nLayerNo", "type": "DWORD", "note": ""}, {"off": "0x04", "name": "fSaved", "type": "DWORD", "note": ""}, {"off": "0x08", "name": "pFloors", "type": "AutoMapCell*", "note": ""}, {"off": "0x0C", "name": "pWalls", "type": "AutoMapCell*", "note": ""}, {"off": "0x10", "name": "pObjects", "type": "AutoMapCell*", "note": ""}, {"off": "0x14", "name": "pExtras", "type": "AutoMapCell*", "note": ""}, {"off": "0x18", "name": "pNextLayer", "type": "AutoMapLayer*", "note": ""}], "refs": []} {"id": "struct.AutoMapCell", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/jankowskib/D2Ex2/master/D2Structs_113D.h", "desc": "A single automap tile node (cell number, pixel position, weight) linked as a binary tree via pLess/pMore. Verbatim source spelling is AutoMapCell.", "fields": [{"off": "0x00", "name": "fSaved", "type": "DWORD", "note": ""}, {"off": "0x04", "name": "nCellNo", "type": "WORD", "note": ""}, {"off": "0x06", "name": "xPixel", "type": "WORD", "note": ""}, {"off": "0x08", "name": "yPixel", "type": "WORD", "note": ""}, {"off": "0x0A", "name": "wWeight", "type": "WORD", "note": ""}, {"off": "0x0C", "name": "pLess", "type": "AutoMapCell*", "note": ""}, {"off": "0x10", "name": "pMore", "type": "AutoMapCell*", "note": ""}], "refs": []} {"id": "struct.Control", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/noah-/d2bs/master/D2Structs.h", "desc": "A UI control/widget (button, textbox, etc.) with position, size, handler pointers, linked text and edit state. Only a forward declaration exists in 113D, so the d2bs body is used.", "fields": [{"off": "0x00", "name": "dwType", "type": "DWORD", "note": ""}, {"off": "0x04", "name": "_1", "type": "DWORD*", "note": "unsure? definitely a ptr but not obvious, usually points to 6 when dwType is 6 I think"}, {"off": "0x08", "name": "dwDisabled", "type": "DWORD", "note": ""}, {"off": "0x0C", "name": "dwPosX", "type": "DWORD", "note": ""}, {"off": "0x10", "name": "dwPosY", "type": "DWORD", "note": ""}, {"off": "0x14", "name": "dwSizeX", "type": "DWORD", "note": ""}, {"off": "0x18", "name": "dwSizeY", "type": "DWORD", "note": ""}, {"off": "0x1C", "name": "_2", "type": "DWORD*", "note": "some sort of function (maybe click?); preceding source comment: I think _2 thru _9 are a handler table of some sort"}, {"off": "0x20", "name": "_3", "type": "DWORD", "note": ""}, {"off": "0x24", "name": "_4", "type": "DWORD*", "note": "some sort of function"}, {"off": "0x28", "name": "_5", "type": "DWORD*", "note": ""}, {"off": "0x2C", "name": "_6", "type": "DWORD", "note": ""}, {"off": "0x30", "name": "_7", "type": "DWORD*", "note": "ptr to something..."}, {"off": "0x34", "name": "_8", "type": "DWORD*", "note": "another random ptr... mostly dead ends when I examined them"}, {"off": "0x38", "name": "_9", "type": "DWORD", "note": ""}, {"off": "0x3C", "name": "pNext", "type": "Control*", "note": ""}, {"off": "0x40", "name": "_10", "type": "DWORD", "note": ""}, {"off": "0x44", "name": "unkState", "type": "DWORD", "note": "_11 0 when button avail to be clicked 1 when greyed - still need to look at this more"}, {"off": "0x48", "name": "pFirstText", "type": "ControlText*", "note": ""}, {"off": "0x4C", "name": "pLastText", "type": "ControlText*", "note": ""}, {"off": "0x50", "name": "pSelectedText", "type": "ControlText*", "note": ""}, {"off": "0x54", "name": "dwSelectEnd", "type": "DWORD", "note": ""}, {"off": "0x58", "name": "dwSelectStart", "type": "DWORD", "note": ""}, {"off": "0x5C", "name": "wText[256]", "type": "wchar_t", "note": "union member, anonymous struct: Textboxes"}, {"off": "", "name": "dwCursorPos", "type": "DWORD", "note": "union member, anonymous struct: Textboxes (no offset comment in source)"}, {"off": "", "name": "dwIsCloaked", "type": "DWORD", "note": "union member, anonymous struct: Textboxes (no offset comment in source)"}, {"off": "0x5C", "name": "_12[2]", "type": "DWORD", "note": "union member, anonymous struct: Buttons (overlaps textbox members at 0x5C)"}, {"off": "0x6C", "name": "wText2[256]", "type": "wchar_t", "note": "union member, anonymous struct: Buttons"}], "refs": []} {"id": "struct.Waypoint", "kind": "struct", "trust": "sourced", "author": "D2 community headers \u2014 D2Ex2/D2Structs_113D.h (jankowskib) + d2bs (noah-)", "source_url": "https://raw.githubusercontent.com/noah-/d2bs/master/D2Structs.h", "desc": "A single waypoint activation record (flags bitfield). Only a forward declaration exists in 113D, so the d2bs body is used.", "fields": [{"off": "0x00", "name": "flags", "type": "BYTE", "note": ""}], "refs": []} {"id": "note.esoteric_synthesis", "kind": "note", "trust": "verified", "author": "The Esoteric Path", "desc": "# The Esoteric Synthesis \u2014 D2 is a graph projected through one lens\n\n*Our own synthesis, fusing the ingested canon with what we verified against the binary. This is the\n\"make it ours\" layer: the basic facts assembled into the single architecture that explains our whole hunt.*\n\n## 1. The graph (what exists) \u2014 screen-independent, seed-deterministic\n`Game` owns everything. The spine is `Game -> Act -> Level -> Room2 -> Room1 -> UnitAny`.\n- **Room2** is the static, seed-deterministic *description* of a room; **Room1** is the live *instance*,\n hydrated only near players. World state is data, not pixels.\n- **UnitAny** is the universal entity: a tagged union with three arms -- **A** `pUnitData` (*what it is*:\n Player/Monster/Object/Item), **B** `pPath -> Room1 -> ... -> Act` (*where it is*), **C** `pInfo`/skills\n (*what it can do*). Stats (`pStats -> StatListEx -> Stat[]`) and inventory (`pInventory -> item UnitAny\n list`) are a **parallel graph off the same root** -- same UnitAny, disjoint bodies, meeting only at the screen.\n- Nothing in this graph stores a screen coordinate. Ever.\n\n## 2. The lens (how it reaches the screen) \u2014 one render context per frame\nEvery tile and unit is projected through ONE struct we verified, [[struct.D2Client_RenderContext]]\n(`*0x6FBCC3C4`): `screenX = draw_left(+0x04) - scroll_x(+0x24) + worldX`. The renderer walks the Arm-B\nspine (`Act -> Level -> Room2 -> Room1 -> unit list`), turns each entity's room-space Path position into a\n`CellContext.dwPosX`, and blits its `GfxCell` through `D2Client -> D2gfx -> D2Glide -> D2DX`. The lens is\nthe *only* place world->screen happens.\n\n## 3. The phenomenon (the theory that explains everything we've chased)\nOpening a panel **does not touch the graph** -- it mutates the **lens**:\n- `offX -> draw_left(+0x04) = -320` -> the **shift** ([[finding.terrain_shift_is_offx_ctxL]])\n- `draw_right(+0x0C)` narrowed to ~960 -> the **issue-clip**\n\nSo the shift, the clip, and the world/units desync are **one cause**: a view-state mutation\n([[reframe.one_cause_view_state]]). The graph is innocent; the lens moved. Units take an *extra* -320 in\nPASS2 (a second lens-read) -- that is the 2x desync. And the residual black is a **second lens downstream**:\neven when we widen `draw_right` and D2Glide submits the far tiles (338 verts into [960,1280)), **D2DX drops\nthem** ([[finding.clip_is_d2dx_drop_confirmed]]). Two lenses, one graph.\n\n## 4. Why this makes the fix tractable\nBecause the graph is screen-independent (the canon *proves* it), we can render the whole Arm-B walk in a\n**no-panel lens** (offX=0, draw_right=DispW) and composite the panel on top -- safely, without touching the\n173 offX readers or any world struct. The canon tells us it's safe; our RE tells us the exact two knobs\n(the D2Client lens + the D2DX drop). That is the entire path to ZERO black with the world behind the panel.\n\n**One line:** *D2 is a screen-independent object graph drawn through a single per-frame lens; every symptom\nwe've chased is the lens being rewritten when a panel opens -- never the graph.*", "refs": ["struct.D2Client_RenderContext", "finding.terrain_shift_is_offx_ctxL", "reframe.one_cause_view_state", "finding.clip_is_d2dx_drop_confirmed", "struct.UnitAny"]} {"id": "note.units_synthesis", "kind": "note", "trust": "sourced", "author": "The Esoteric Path \u2014 canon synthesis (grounded + cited)", "desc": "# The units struct web (D2 1.13c) and how it reaches our render path\n\nGrounding: UnitAny field offsets are from the in-repo 1.11b Structure Reference (`research/kb/corpus/forum/highvalue/t47809.json`); the render-context side is from `grimoire/symbols.jsonl` (`struct.D2Client_RenderContext`, `D2Client.DrawRooms`, `D2Client.FloorFlush`). Offsets are stable UnitAny-relative through 1.13c. Room1/Room2/Level/Act are named by their canonical fields; the repo confirms the *roots* of that chain (see the lifecycle section) but not every byte offset inside it, so those inner offsets are named, not asserted numerically.\n\n## 1. UnitAny is the hub \u2014 a tagged union with three \"arms\"\n\nEvery player, monster, object, item, missile and tile is one `UnitAny`. It carries a type/id header and then hands off to per-type payloads through three pointer arms:\n\n- **Identity header**: `+0x00` dwType, `+0x04` dwTxtFileNo, `+0x0C` GUID (links a server unit to its client twin), `+0x10` eMode (anim/action mode), `+0x18` actNo, `+0x28` dwInitSeed.\n- **Arm A \u2014 what it *is*** (`+0x14 pUnitData`, a union of 5 classes per the repo): `pPlayerData` / `pMonsterData` / `pObjectData` / `pMissileData` / `pItemData`. Which member is live is selected by dwType. \"Note, there is no pTileData.\"\n- **Arm B \u2014 where it *is*** (`+0x2C pPath`, a union of 2 classes per the repo): `pStaticPath` (Objects, VisTiles, Items) vs `pDynamicPath` = **Path** (Players, Monsters, Missiles).\n- **Arm C \u2014 what it can *do*** (`+0xA8 pSkills`): the skill controller = **Info**, \"a list of all skills the unit has (pointers to pSkill).\"\n\nOther hub fields that matter for lifecycle/draw: `+0x5C pStatListEx`, `+0x60 pInventory`, `+0xE4 pPrevUnit` (prev in the unit-type list), `+0xE8 pPrevUnitInRoom` (\"previous unit in the current room\").\n\n## 2. Arm A \u2014 the payload structs\n\n- **PlayerData**: name + quest/waypoint blocks; the human-facing identity. It's the union member picked when dwType == player.\n- **MonsterData** (sizeof 0x60): `+0x00 pMonStats` = the monstats.txt record; `+0x04 Components[16]` = the component ids (HD/TR/LG/...) that drive which cels get drawn.\n- **ObjectData**: points to its objects.txt/ObjectMode record \u2014 the static-world furniture arm.\n- **ItemData** (sizeof 0x74): quality/flags/fingerprint. Items also thread through `pInventory` (Inventory: `+0x08 pOwnerUnit`, `+0x0C pFirstItem`, `+0x14 pInvInfo` equipped-gear list) \u2014 i.e. an item's UnitAny is reachable both as a standalone unit and as a node inside another unit's inventory.\n\nThese are pure data payloads: they never point back up to rooms. Position lives entirely in Arm B.\n\n## 3. Arm B \u2014 Path \u2192 Room1 \u2192 Room2 \u2192 Level \u2192 Act (the spatial spine)\n\nThis is the chain that matters for rendering, because a unit's *screen* position is derived from its *Path* position projected through the room it sits in.\n\n- **Path** (dynamic, for moving units) carries the fine sub-tile position (dwPosX/dwPosY plus target/offset fields) and a back-pointer to its **Room1**. **StaticPath** (objects/tiles/items) is the lean version: a room pointer + a fixed tile position (no velocity, no targets), because static things never move.\n- **Room1** = the collision/active room: its unit list is what the draw walks (units chained via `UnitAny+0xE8 pPrevUnitInRoom`), it holds the CollMap, near-room pointers, and a link up to **Room2**.\n- **Room2** = the DRLG/preset room: geometry, presets, near-room graph, and the link up to **Level**.\n- **Level** = the area (its levelno indexes Levels.txt), owning its Room2 list and linking up to **Act**.\n- **Act** = `pDrlgAct`, reachable directly off the unit at `UnitAny+0x1C` and rooted in the game at `pGame->pDrlgAct[5]` / `pGame->pDrlgRoomList[5]`.\n\nSo `UnitAny \u2192 pPath \u2192 (Room1 \u2192 Room2 \u2192 Level \u2192 Act)` is how any unit answers \"which act/level am I in, and where,\" and the reverse (`Act \u2192 Level \u2192 Room2 \u2192 Room1 \u2192 unit list`) is exactly the order the world renderer iterates.\n\n## 4. Arm C \u2014 Info \u2192 Skill \u2192 SkillInfo\n\n`UnitAny+0xA8 pSkills` \u2192 **Info** (the per-unit skill controller) \u2192 a linked list of **Skill** nodes (level, charges, left/right assignment) \u2192 each Skill's **SkillInfo** = the Skills.txt/skilldesc record. This arm is orthogonal to rendering (it drives casting/sequence via `pSeqMode` at `UnitAny+0x30`), included here to complete the hub.\n\n## 5. Ownership & lifecycle\n\n- **Owner**: `pGame` owns everything \u2014 the per-act DRLG (`pDrlgAct[5]`), the room lists (`pDrlgRoomList[5]`), and the unit lists. Units do not own their Path/Data payloads' *world*; they borrow into the game-owned room/level/act graph via Arm B. A unit's own `pUnitData`, `pPath`, `pInventory`, `pStatListEx`, and `Info` are allocated with it.\n- **Membership**: a unit lives in two intrusive lists simultaneously \u2014 the global type/GUID bucket (`pPrevUnit`, hashed by GUID&127) and its current room (`pPrevUnitInRoom`). When a unit crosses a room boundary its Path's Room1 pointer is re-linked and it moves room lists; that re-link is the seam the renderer sees.\n- **Determinism**: `dwInitSeed` (unit) + `GameSeed` (game) make spawns reproducible.\n- **Client/server twins**: GUID ties a client `UnitAny` to its server one; several hub fields (`+0x64`, `+0x80`, `+0xD8`) are overloaded client-vs-server.\n\n## 6. How this all lands in OUR render work\n\nThe world draw is a walk of the Arm-B spine, and each unit it reaches is **projected through the render context** \u2014 the one struct we've been fighting.\n\n- **The projection**: for any tile/unit, `screenX = ctx+0x04 \u2212 ctx+0x24 + tileAbsX` and `screenY = tileAbsY \u2212 ctx+0x28 + ctx+0x08` (`struct.D2Client_RenderContext`; matches `D2Client.FloorFlush`). `tileAbsX` comes from the unit's Path/StaticPath room-space position; the two ctx terms are the draw-window origin (`+0x04` draw_left) and the camera scroll (`+0x24` scroll_x).\n- **The room iteration is clipped by the ctx draw-window**: `D2Client.DrawRooms` (0x7A9F0) builds its room-iteration RECT from `ctx` draw-window + scroll (`band = [scrollX, scrollX + (R\u2212L)]`) and culls any tile with `tileWorldX > RECT.R`. So `ctx+0x0C` (draw_right) is literally the bound on how far along the Room1/Room2 walk we draw. That is the tile/room draw path the units hang off of.\n- **The shift = the projection's origin term** (`finding.terrain_shift_is_offx_ctxL`): opening a side panel writes `offX (0x6FBCC418) = \u2212320` into `ctx+0x04`, so every tile *and* unit derived from the same Path\u2192Room projection slides \u2212320 (1\u00d7). scroll_x (`ctx+0x24`) is untouched \u2014 the pan is entirely the draw-window origin, not the camera.\n- **Why units desync 2\u00d7**: floor tiles and units read the *same* 1\u00d7 projection, yet units land at \u2212640. The extra \u2212320 is applied in the unit pass (PASS2), not in the shared ctx term \u2014 consistent with offX being read at 173 sites while the units path re-reads it. The Arm-A/Arm-B split is why: terrain tiles are projected once off the room; unit sprites are re-projected on top with a second offX application.\n- **`reframe.one_cause_view_state`**: the shift, the play-area narrowing, and the world-vs-units desync are one thing \u2014 opening a panel mutates the world **view-state** held in this render context (offX + draw_right). The clean fix is to render the whole Arm-B walk in the no-panel view-state (offX=0, draw_right=DispW) and composite the panel on top, so terrain and units share one coherent projection again.\n- **The remaining black is downstream of all of this** (`finding.clip_is_d2dx_drop_confirmed`): even when we widen `ctx+0x0C` so `DrawRooms` iterates the full room band and D2Glide submits the far tiles (verts reach x\u22481264, 338 in [960,1280)), D2DX drops the dead-zone geometry. So the units-struct \u2192 render-context chain correctly *produces* the far-right world geometry; the loss is past the D2Glide\u2192D2DX seam, not in the unit/room walk.\n\n**One-line takeaway**: `UnitAny` is a tagged union \u2014 Arm A says *what*, Arm B (`pPath \u2192 Room1 \u2192 Room2 \u2192 Level \u2192 Act`) says *where*, Arm C says *what it can do*. The renderer walks Arm B (Act\u2192Level\u2192Room2\u2192Room1\u2192unit list) and turns each unit's room-space Path position into pixels via the render-context origin/scroll/draw-window; the panel-open \"shift\" and \"clip\" are just that render context's origin (`+0x04`=offX) and right-bound (`+0x0C`) being rewritten, with the residual black living downstream in D2DX.", "refs": ["struct.D2Client_RenderContext", "finding.terrain_shift_is_offx_ctxL", "reframe.one_cause_view_state", "finding.clip_is_d2dx_drop_confirmed", "struct.UnitAny", "struct.Path", "struct.Info"]} {"id": "note.world_synthesis", "kind": "note", "trust": "sourced", "author": "The Esoteric Path \u2014 canon synthesis (grounded + cited)", "desc": "# The \"world\" struct graph \u2014 synthesis note\n\nSource of truth for every field/offset below: `D:\\_SERVER\\esoteric-path\\tools\\dll-work\\plugy-src\\chaos\\Commons\\D2UnitStruct.h`. That header uses Yohann's older names; our own patch logs use the canonical names (`reference/EP-assembly-notes/townCheck.asm`: `CheckIfRoomIsTown(Room1* pRoom)`, `GetTownFromAct(Act* pDrlgAct)`, `GetActFromLevel`). Name map: **Room1 = `Room`, Room2 = `RoomEx`, Act = `ActMap`, ActMisc = `ActData`**; Level, PresetUnit unchanged; RoomTile is the list hung at Room2's warp-tile pointer.\n\n## The core insight: two graphs, not one\nThe world is a **static description graph** (Room2 \u2192 Level \u2192 ActMisc, seed-deterministic, screen-independent) with a **live instance graph** (Room1) lazily allocated on top of it. UnitAny rides the live graph; the renderer is a third, per-frame layer that never touches either \u2014 which is the whole reason the terrain/click bugs are view-state, not world-state.\n\n## The pointer chain (UnitAny \u2192 \u2026 \u2192 Act)\nGrounded in real fields:\n- **`Unit.path` (+2C, `Path*`)** and `Unit.ptPos` (+38). `Path.ptRoom` (+1C) \u2192 the **Room1** the unit occupies. Path also caches the unit's `x`/`y` (+0C/+10) and `mapx`/`mapy` (+02/+06). Unit also caches `ptAct` (+1C) and `ptGame` (+80) directly.\n- **Room1 (`Room`)** `ptRoomEx` (+10, `RoomEx*`) \u2192 its **Room2**. (Reverse of Room2\u2192Room1.)\n- **Room2 (`RoomEx`)** `ptLevel` (+58, `Level*`) \u2192 its **Level**.\n- **Level** `ptActData` (+1B4, `ActData*`) \u2192 **ActMisc**. The canonical \"\u2192 Act\" edge closes via **`ActData.ptActMap` (+46C)** \u2192 the small **Act (`ActMap`)**; ActMisc\u2194Act is mutual (`ActMap.ptActData` +48).\n\nSo the full walk is: `Unit.path \u2192 Path.ptRoom(Room1) \u2192 Room1.ptRoomEx(Room2) \u2192 Room2.ptLevel(Level) \u2192 Level.ptActData(ActMisc) \u2192 ActMisc.ptActMap(Act)`.\n\n## Ownership & lifecycle\n- **Roots live on Game.** `Game.mapAct[5]` (+BC, `ActMap*`) \u2014 one Act per act. `ActData.ptGame` (+9C) points back up; `ActMap.ptFirstRoom` (+10) and `ActMap.ptActData` (+48) fan down. `ActData` owns the DRLG seeds (`seed1`/`seed2` +0/+4), difficulty (+450), room count (`nbRooms` +8), and the special tomb-level fields (`nTalRashaTombLevel` +94, `nBossMummyTombLevel` +484).\n- **Level is the per-area container**, chained by `ptNextLevel` (+1AC) into the act's level list; it carries `levelNo` (+1D0, the levels.txt Id), `levelType` (+1C0), its own `seed1/2` (+1C4/+1C8), and bounds `posX/Y/sizeX/Y` (+1C\u2026+28). `Level.ptFirstRoomEx` (+10) heads the level's **Room2** list.\n- **Room2 = persistent description.** It exists for the level's whole lifetime, chained by `ptNextRoomEx` (+24); near-graph in `roomExNear` (+08) / `roomsNearCount` (+2C); layout in `posX/Y/sizeX/Y` (+34\u2026+40, room/tile units); `presetType` (+48); `roomFlags` (+28).\n- **Room1 = transient instance.** `Room2.ptRoom` (+30) is **NULL until the room is activated**; when a room comes into play a Room1 is allocated and back-linked (`Room1.ptRoomEx`). Room1 holds the runtime-only state: `coll` (+20, collision map), the room's unit list head `ptFirstUnit` (+74, walked via `Unit.ptNextUnitInRoom` +E8), the active near-set `ptNearRooms`/`nbNearRooms` (+00/+24), collision-space bounds `startX/Y/sizeX/Y` (+4C\u2026+58), and `ptNextRoom` (+7C) chaining the currently-active Room1s. Room1s are created/destroyed as units move; Room2s are not. That Room2-is-data / Room1-is-live split is the lifecycle in one sentence.\n\n## What hangs off Room2: PresetUnit and RoomTile\n- **PresetUnit** \u2014 the fixed seeded contents of a room (chests, waypoints, superuniques, preset monsters). Each carries `unitType` (+0), `txtFileNo` (+4), room-local `xPos`/`yPos` (+C/+10), and chains via `pNext` (+1C). The list hangs off Room2 (canonical `Room2.pPreset`; note this repo's `RoomEx` header truncates at `ptLevel` +58 and does not expand the preset field \u2014 the PresetUnit struct itself is defined and verified).\n- **RoomTile** \u2014 the per-Room2 warp-tile list at **`RoomEx.ptWarpTiles` (+4C)** (typed `void*` in this header). Each RoomTile links a spot in the room to a level transition; this is the structural basis of the warp/adjacency graph that `Vis/Warp` in levels.txt feeds (see `kb/08-levels-maps.md`).\n\n## Connection to our render work\nThe renderer consumes the **live** graph only and lays a view-state on top:\n- **Tile/room draw path.** D2Client walks the active **Room1** list and, per room, emits its terrain tiles plus its unit list (`ptFirstUnit`). World positions are Room1 subtile coords (`startX/Y`, `sizeX/Y`); nothing screen-relative is stored on any world struct.\n- **The render context** (`struct.D2Client_RenderContext`) is where world\u2192screen happens: it holds `offX` and the draw-window/clip rect. The concrete knobs we've located are the resolution globals in `kb/15-EP-assembly-notes-index.md` (`GeneralDisplayWidth [6FB8BC48]`, `GeneralDisplayHeight [6FB8BC4C]`) and the tile-extent edits (`!Definite.asm` `ADD ECX,-2F \u2192 50`, `[[6F865B04]] = screen height`; `TileRendering.asm`, `viewmatrix110.asm`).\n- **Terrain shift = offX, not world.** Because Room1 tile coords are fixed and seed-deterministic, any apparent terrain movement is the render context's `offX`/`ctxL` draw-window left edge changing (`finding.terrain_shift_is_offx_ctxL`) \u2014 i.e. the view-state, not the room graph.\n- **One cause = view-state** (`reframe.one_cause_view_state`). The terrain-shift and the bottom-bar click-miss are the same defect: the world struct graph is intact and screen-independent, while the per-frame view-state (render context draw-window + D2Client's panel/resolution geometry) is what moved after the SGD2FreeRes provider swap. The click side is the input twin of the draw side (`clickThrough.txt`: `6FAD81F5` JNZ/JMP gate).\n- **Clip is a d2dx drop, not engine culling** (`finding.clip_is_d2dx_drop_confirmed`). The engine's room enumeration (Room1 near-list) correctly yields the edge rooms/tiles; the missing band is dropped downstream by the d2dx/SGD2FreeRes tile culling at the wrapper, confirmed in `kb/14-rendering-stack.md` (the 47px void region + motion-prediction tile culling). So edge loss is renderer-side clip, cleanly separable from the world structs above it.\n\n## Punchline\nRoom2/Level/ActMisc/Act are a seed-deterministic, screen-agnostic description; Room1 is the live overlay the renderer and units actually touch; and every \"the world moved\" symptom we've chased lives one layer higher still \u2014 in the render context's view-state \u2014 never in these structs.", "refs": ["struct.D2Client_RenderContext", "finding.terrain_shift_is_offx_ctxL", "reframe.one_cause_view_state", "finding.clip_is_d2dx_drop_confirmed", "struct.Room1", "struct.Room2", "struct.Level", "struct.Act"]} {"id": "note.stats_inv_synthesis", "kind": "note", "trust": "sourced", "author": "The Esoteric Path \u2014 canon synthesis (grounded + cited)", "desc": "# stats_inv \u2014 synthesis note (1.13c)\n\nEverything here hangs off one root: the player `UnitAny`. Two independent pointer graphs grow from it, and they only reconverge at the screen:\n\n- **WHERE the unit is** \u2192 `pPath \u2192 Room1 \u2192 Room2 \u2192 Level \u2192 Act` (feeds the world tile/room draw).\n- **WHAT the unit is** \u2192 `pStats \u2192 StatListEx \u2192 Stat[]` and `pInventory \u2192 Inventory \u2192 item UnitAny list` (feeds the inventory/character *panel* draw).\n\nThe six `stats_inv` structs are the second graph. `InventoryLayout` is the odd one out \u2014 it is not in the unit graph at all; it is the static screen-space stencil the panel draw borrows.\n\n---\n\n## 1. The stat chain\n\n```\nUnitAny\n +0x5C pStats \u2500\u2500 StatListEx (the unit's ONE aggregated/\"full\" list)\n Stats(StatVector) : pStat @+0x24 \u2192 Stat[ ] , wCount @+0x28\n fpStatExpires @+0x38 (contributor-removed callback)\n pNext / pMyLastList \u2500\u2500 chain of contributor StatList nodes\n```\n\n- **`Stat`** \u2014 one record, 8 bytes: `wSubIndex`(+0x00, WORD) \u00b7 `wStatIndex`(+0x02, WORD = the ItemStatCost id) \u00b7 `dwStatValue`(+0x04, DWORD). The corpus lists this verbatim: `iStatIndex[0]`/`iStatID[0]`/`iStatValue[0]` at 0/2/4, array packed 8-byte stride, kept sorted by id. `wSubIndex` is why one id can appear twice (e.g. per-skill / per-class stats).\n- **`StatEx`** \u2014 the same `{wSubIndex, wStatIndex, dwStatValue}` triple as it lives in the *extended* vector, carrying the extra bookkeeping the \"Ex\" (full) list needs to know **which contributor list a value came from** so it can be re-folded or expired. It is the element type of the aggregated list; `Stat` is the element type of a plain modifier list.\n- **`StatList`** \u2014 the base node/header: its `Stats` StatVector (`pStat`@+0x24, `wCount`@+0x28 \u2014 corpus-grounded) points at the `Stat[]` this node contributes, plus a `pNext` link. A single state (aura, curse, buff) or a single equipped item owns exactly one of these.\n- **`StatListEx`** \u2014 the unit-owned superset that `UnitAny.pStats` actually points at. It embeds the base `StatList` and adds the multi-layer value vectors, the `pUnit` back-pointer, and `fpStatExpires`(+0x38, corpus-grounded) \u2014 the callback invoked when a contributor list is torn off. The `+0x58` field the corpus flags \"inside StatListEx\" belongs to this extra region.\n\n**Fold/expire lifecycle (the ownership story):** each equipped item and each active state produces its *own* `StatList` of raw modifiers, links it into the owner's `StatListEx` chain via `pNext`, and its values get summed into the aggregated `StatEx[]`. When the item is removed or the state ends, the node is unlinked and `fpStatExpires` recomputes the full list. `ITEMS_UpdateTransferredProperties` (corpus, `D2Game.0x6FC424E0`, args `bUpdateStatList`) is the server-side driver of exactly this. So: the unit **owns** one `StatListEx`; every contributor is **owned by its source** and has list-scoped lifetime, not unit-scoped.\n\n---\n\n## 2. The inventory chain\n\n```\nUnitAny\n +0x60 pInventory \u2500\u2500 Inventory\n dwSignature @+0x00 (0x1020304 sanity tag)\n pOwner \u2500\u2500 back to this UnitAny (cycle)\n pFirstItem \u2500\u25ba item UnitAny \u2500\u25ba ... \u2500\u25ba pLastItem (equipped/stored items)\n pCursorItem (item on the mouse)\n```\n\n- **`Inventory`** \u2014 the runtime container. `pOwner` closes the cycle back to the unit; `pFirstItem\u2026pLastItem` is the linked list of item `UnitAny`s. Each item is a full `UnitAny` with **its own `pStats` (StatListEx)** \u2014 that is the physical link between the two structs: an item's stat list is a contributor that folds into the wearer's aggregated list (section 1). Corpus D2Common sigs (`D2Common_FindStackTarget(Inventory*, ...)`, `InventoryHasRoomForItem(D2InventoryStrc*, ...)`) operate on exactly this node.\n- **`InventoryLayout`** \u2014 **not reached by any pointer from `Inventory`.** It is the static per-panel/per-class grid descriptor: pixel bounds `Left/Right/Top/Bottom` + `SlotWidth/SlotHeight` (cells) + per-cell pixel size. Lifetime = process (a data table), not the unit. The inventory-panel draw (`D2Client.0x3EAC0` in the ref; `UI_INVENTORY_DrawItemBackground(D2InventoryGridInfoStrc*, nX, nY, nItemWidth, nItemHeight, \u2026)` in the corpus) *reads* it to place each `Inventory` item's cell. So `Inventory` says *which items and where in grid-cells*; `InventoryLayout` says *where those cells land in screen pixels*.\n\n---\n\n## 3. Why this sits parallel to the position chain\n\nThe map chain `UnitAny.pPath \u2192 Path.pRoom1 \u2192 Room1.pRoom2 \u2192 Room2.pLevel \u2192 Level \u2192 Act` is the *other* graph. It is what `DrawRooms` (0x7A9F0) walks: it iterates the `Room1` linked list (`Room1.pNext` @+0x74, per-room units via `UnitAny` room-next @+0xE8 \u2014 both corpus-grounded) and projects each tile through the render context. The stat/inv graph never touches tiles; it drives the panel. **Same root, disjoint bodies, they only collide in screen space.**\n\n---\n\n## 4. Where it meets our render work\n\nThe collision point is the render context \u2014 [[struct.D2Client_RenderContext]] (`*0x6FBCC3C4`), which *is* the world view-state. Tile projection is `screenX = ctxL(+0x04) \u2212 scrollX(+0x24) + tileAbsX`.\n\n- **Opening the inventory is the trigger for both graphs at once.** The panel it opens is drawn from graph #2 (`pInventory` items placed via `InventoryLayout.Left/Right/Top/Bottom`). That panel occupies the right band \u2014 and to make room, the panel-open handler rewrites graph-#1's view-state: `offX \u2192 ctx+0x04 = \u2212320` and narrows `ctx+0x0C` toward 960.\n- The \u2212320 world shift is [[finding.terrain_shift_is_offx_ctxL]]: the *whole* floor pan is `offX(0x6FBCC418) \u2192 ctx+0x04`, `scrollX` untouched. So `InventoryLayout`'s `Left` edge (where the panel starts, screen-space) is conceptually the same X-coordinate the world view is being shoved away from \u2014 the panel's static geometry and the world's dynamic `ctxL`/`draw_right` are fighting over one screen column.\n- This is the whole point of [[reframe.one_cause_view_state]]: the dead zone, the camera shift, and the world/units desync are **one cause** \u2014 opening the panel changes the world view-state. The clean target is to render graph #1 in the *no-panel* view-state (offX = 0, full `ctx+0x0C`) and composite the graph-#2 panel (its `InventoryLayout` region) on top, so the two graphs stop colliding.\n- Caveat we proved: neutralizing the ctx window is necessary but not sufficient for the black band \u2014 [[finding.clip_is_d2dx_drop_confirmed]]. Once the world is un-shifted, valid floor geometry reaches `x\u2265640/960` at the D2Glide\u2192D2DX seam (submit max 1264\u20131296, 338 verts in the dead zone) and is still dropped **downstream in D2DX**, not by `ctx+0x0C`. So the `stats_inv`/panel side dictates *where* the world must not draw; the D2DX target extent dictates *whether* it can.\n\n**One-line takeaway:** `pStats`/`pInventory` and `pPath` are twin graphs off `UnitAny`; the inventory panel is drawn from the former via the static `InventoryLayout` stencil, and the act of opening it is precisely what rewrites the render-context view-state that our terrain-shift and dead-zone work is chasing.\n\n---\n\n### Offsets: sourcing\n- Corpus/repo-grounded: `UnitAny.pStats` +0x5C; `StatList.Stats` pStat +0x24 / wCount +0x28; `StatListEx.fpStatExpires` +0x38; `Room1.pNext` +0x74; unit room-next +0xE8; `Inventory` sigs via `D2InventoryStrc`.\n- Canonical D2Structs.h (not re-measured vs the 1.13c binary here): `UnitAny.pInventory` +0x60; `Inventory.dwSignature/pOwner/pFirstItem/pLastItem/pCursorItem`; `InventoryLayout.Left/Right/Top/Bottom + SlotWidth/SlotHeight`. Verify against the live binary before hooking.", "refs": ["struct.D2Client_RenderContext", "finding.terrain_shift_is_offx_ctxL", "reframe.one_cause_view_state", "finding.clip_is_d2dx_drop_confirmed", "struct.StatListEx", "struct.Inventory", "struct.InventoryLayout"]} {"id": "note.gfx_ui_synthesis", "kind": "note", "trust": "sourced", "author": "The Esoteric Path \u2014 canon synthesis (grounded + cited)", "desc": "# gfx_ui structs \u2014 how they connect (1.13c RE reference)\n\n**One-line thesis:** the eight gfx_ui structs are *content* (what a sprite/tile/overlay looks like and where it wants to sit in world space). None of them owns the world\u2192screen transform \u2014 that lives entirely in the render context. So a panel-open never changes a single field in these structs; it changes `D2Client_RenderContext`, and every one of these structs re-projects through the new view-state. That's why the shift/clip fix belongs at the view-state, not here.\n\n## Confidence tiers (hostile-reader honesty)\n- **Project-verified (exact offsets, from our grimoire/1.13c binary):** `D2Client_RenderContext` layout, the FloorFlush/DrawRooms projection, the automap fns (`NewAutomapCell` 0x703C0, `AddAutomapCell` 0x71EA0, `InitAutomapLayer_I` 0x733D0, `DrawAutomapCell` D2GFX 0x7C80, `AutomapLayer*` var 0x11CF28), and the \"Lit\" cel path.\n- **Canonical D2Structs.h field names (community-standard, and our own d2-re-reference \u00a73 states \"layouts are stable across versions\"):** the sprite triad, automap pair, `Control`, `Waypoint`, `Light`. Field *names* below are dependable; where a byte offset for these isn't in our verified set I name the field and flag it, rather than invent an offset.\n\n---\n\n## 1. The sprite triad \u2014 GfxInfo \u2283 GfxCell, driven by CellContext\n\nOwnership is a strict containment + a transient pointer-in:\n\n```\nGfxInfo (loaded DC6/DCC file) CellContext (per-draw state)\n dwVersion / eFormat nCellNo \u2500\u2500 frame index \u2500\u2500\u2510\n numdirs, numcells pCellFile \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u25ba GfxInfo\n cells[] \u2500\u2500\u25ba GfxCell* (per dir \u00d7 frame) dwPosX, dwPosY \u2502\n \u2502 \u2502\n \u25bc GfxInfo.cells[nCellNo]\u2502\n GfxCell (one frame) \u25c4\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n flags, width, height\n xoffs, yoffs (sprite-local anchor, NOT screen)\n lpParent \u2500\u2500\u25ba back to owning GfxInfo\n length, cols[] (RLE pixel data)\n```\n\n- **GfxInfo owns GfxCell.** `GfxInfo.numcells` sizes the `cells[]` table; each `GfxCell.lpParent` points back to its `GfxInfo`. GfxCells have **no independent lifecycle** \u2014 they live and die with the file. Lifetime = file load \u2192 cache eviction.\n- **CellContext owns nothing; it *selects*.** `pCellFile` \u2192 a `GfxInfo`; `nCellNo` indexes `GfxInfo.cells[]` to pick the `GfxCell`; `dwPosX/dwPosY` say where to blit it. It is the per-draw cursor, rebuilt every frame.\n- **Key point for us:** `GfxCell.xoffs/yoffs` are *sprite-local* anchors, and `CellContext.dwPosX/dwPosY` are already *screen* coords. The world\u2192screen step that produced those screen coords happened earlier, in the render context (\u00a74). The sprite structs are position-agnostic \u2014 hand the same `GfxCell` a different `dwPosX` and it draws shifted, unchanged.\n\n## 2. Where the tile/floor GfxCells come from \u2014 the world hierarchy\n\nThe classic chain feeds the tile draw path. Named by field:\n\n```\nUnitAny.pPath \u2500\u25ba Path.pRoom1 \u2500\u25ba Room1.pRoom2 \u2500\u25ba Room2.pLevel \u2500\u25ba Level.pMisc \u2500\u25ba ActMisc.pAct \u2500\u25ba Act\n \u2502 \u2502\n Room1.pRoomNext (active-room list) Level.pRoom2First (all rooms in level)\n Room1.pUnitFirst (units in room) Room2.pRoomTiles (tile/gfx data)\n Room1.Coll (collision)\n```\n\n- **DrawRooms** seeds off the player's room (`GetRoomFromUnit` #10331 \u2192 the `Room1` the player's `Path.pRoom1` points at), then iterates the `Room1` list. Per room it runs the per-tile dispatch (tile struct 0x30 bytes; flags `[t+0x14]` bit-test `0x1C000` = DRAW_GROUND|FLOOR|ROOF; orientation `[t+0x1c]`). Each drawn tile resolves to a `GfxCell` and is handed to the cel-blit thunks (\u00a74).\n- **Room1 vs Room2 = lifecycle boundary.** `Room2` is the persistent level-geometry node (always present via `Level.pRoom2First`); `Room1` is the *hydrated/active* instance (`Room2.pRoom1` non-null only near players) that actually carries collision + live units + the tiles that get drawn. Panel-open changes *which* Room1s survive culling, never the Room1/Room2 structs themselves.\n\n## 3. The three overlay structs \u2014 parallel projections, NOT the world path\n\nThese are drawn *outside* the render-context tile path, which is exactly why they don't shift/clip with the world:\n\n- **AutoMapLayer / AutoMapCell** \u2014 one `AutoMapLayer` per `Level` (`AutoMapLayer.nLayerNo` == level no; global head at var **0x11CF28**). Cells hang off the layer's four buckets `pFloors / pWalls / pObjects / pExtras`, each a sorted tree via `AutoMapCell.pLess / pMore`. Each `AutoMapCell` carries `nCellNo` (frame in the automap sprite) + `xPixel/yPixel`. Built by `RevealAutomapRoom` (0x73160) walking a Room's tiles \u2192 `NewAutomapCell` (0x703C0) \u2192 `AddAutomapCell` (0x71EA0); drawn by **`DrawAutomapCell` (D2GFX 0x7C80, takes a RECT\\* cliprect)**. So the automap is a *second, independent* projection of the same Room geometry \u2014 its own coord space, its own clip. It stays whole with a panel open because it never touches `D2Client_RenderContext`.\n- **Light** \u2014 dynamic light entries associated with the active `Room1`/`Act` environment. The connection worth grounding: our live cel handler is **`pfTileDrawLit`** (D2Glide dispatch `+0x9c`, `LiveCelHandler` 0x72F0) \u2014 the *lit* tile blit. Lights modulate the same `GfxCell` pixels as they cross that handler. (Light's finer field layout is the thinnest of the eight in our verified set \u2014 treat its role, not specific offsets, as load-bearing until read off the binary.)\n- **Control** \u2014 the UI-widget chain (`Control.pNext` linked list; `dwType`, `dwPosX/dwPosY`, `dwSizeX/dwSizeY`, plus text/edit fields). Controls are the panel's buttons/boxes, drawn by the **compositor/present** stage of `DrawGame` (body: PASS1 0x44302 \u2192 tiles \u2192 PASS2 0x4436F \u2192 compositor 0x4437B \u2192 present #10040), i.e. *after and over* the world pass \u2014 they sit on top of the dead zone, not in it.\n- **Waypoint** \u2014 `Waypoint.flags` (one byte per waypoint, arrayed). Pure UI/save state surfaced by the **waypoint side panel**, which is one of the panels whose *opening* is the trigger event: `PanelOpenArray` waypoint slot `+0x50`. Opening it fires the exact view-state write that shifts/clips the world (\u00a74). So `Waypoint` is upstream cause-by-association, not a rendered-world participant.\n\n---\n\n## 4. Tie-in to our render work \u2014 the whole point\n\nEverything above pours through **one** transform, the render context.\n\n**`D2Client_RenderContext`** (`struct.D2Client_RenderContext`, instance `*0x6FBCC3C4`) IS the world view-state:\n- `+0x04 draw_left` == **offX** (0 no-panel, **\u2212320** panel-open) \u2014 the shift\n- `+0x0C draw_right` \u2014 iteration bound (1280 no-panel, **960** panel-open) \u2014 the issue-side clip\n- `+0x24/+0x28 scroll_x/scroll_y` \u2014 camera origin (**not** touched by panels)\n\nThe tile projection (FloorFlush / DrawRooms band) is literally:\n```\nscreenX = ctx.draw_left(+0x04) \u2212 ctx.scroll_x(+0x24) + tileAbsX\n```\nThat `screenX` is what becomes a tile's `CellContext.dwPosX`. So:\n\n- **`finding.terrain_shift_is_offx_ctxL`** \u2014 panel-open writes `offX 0\u2192\u2212320` \u2192 `ctx+0x04 0\u2192\u2212320`; `scroll_x` untouched. The floor/terrain GfxCells didn't change; their **CellContext.dwPosX moved \u2212320** because the shared `ctx+0x04` term moved. Confirmed exactly \u2212320 (=\u2212DispW/4), standing still.\n- **`reframe.one_cause_view_state`** \u2014 shift (`+0x04`), clip (`+0x0C` narrow), and the world/units desync are ONE cause: the panel rewrites the view-state. The gfx_ui structs are all downstream of it, so the clean fix authors a coherent no-panel view-state for the whole world draw \u2014 you do **not** patch per-struct or per-sprite, and you keep `ScreenOpenMode` live for UI/culling. (Units pick up an *extra* \u2212320 beyond the shared 1x tile projection \u2014 a separate PASS2/unit-layer source, not the ctx.)\n- **`finding.clip_is_d2dx_drop_confirmed`** \u2014 this exonerates the gfx-struct layer as the blackout cause. With the view-state widened, the tile GfxCells *do* reach the D2Glide\u2192D2DX seam in the dead zone (submit max 1264\u20131296, 338 verts in [960,1280)) and still render **black**. The geometry \u2014 valid GfxCell frames, same path as the [640,960] tiles that paint fine \u2014 is dropped at/after D2DX. So: `ctx+0x0C` governs which GfxCells get **issued/projected**; **D2DX** governs whether the issued verts get **painted**. Two distinct clip layers; neither is a property of the eight structs.\n\n### The stack, one line\n```\nGfxInfo.cells[nCellNo] \u2500\u25ba GfxCell (content, position-agnostic)\n \u2502 positioned by\n \u25bc\nCellContext.dwPosX/Y = D2Client_RenderContext (+0x04 offX, \u22120x24 scroll, +tileAbsX) \u2190 the shift & issue-clip live HERE\n \u2502 blitted via\n \u25bc\nCelBlitThunk \u2192 D2gfx #10001 \u2192 D2Glide pfTileDrawLit (Light modulates) \u2192 grDrawVertexArrayContiguous \u2192 D2DX \u2190 the terminal paint-clip lives HERE\n```\nAutomap (`AutoMapLayer/Cell` \u2192 `DrawAutomapCell`), `Control` (compositor), and `Waypoint` (panel state) all sit *off* this spine \u2014 which is exactly why they never shift or clip when the world does.\n\n**Bottom line for the fix:** don't touch the content structs. Author the no-panel view-state in `D2Client_RenderContext` (neutralize `offX`\u2192`+0x04`, restore `+0x0C`\u2192DispW) AND defeat the D2DX dead-zone drop. Both are view/pipeline layers; the eight gfx_ui structs are innocent bystanders that simply render wherever the view-state tells them to.\n\nSource files: `E:\\Diablo 2 - Esoteric Path\\esoteric-dll\\grimoire\\symbols.jsonl` (render ctx, cel path, D2DX findings), `...\\research\\kb\\reference\\d2-re-reference-1.13c.md` (automap fns, struct-stability note, tile params), `...\\research\\kb\\reference\\panelworld-mods-and-hooks.md` (room/tile draw chain).", "refs": ["struct.D2Client_RenderContext", "finding.terrain_shift_is_offx_ctxL", "reframe.one_cause_view_state", "finding.clip_is_d2dx_drop_confirmed", "struct.GfxInfo", "struct.GfxCell", "struct.CellContext"]} {"id": "attempt.I_noshift_lens", "kind": "finding", "status": "confirmed", "trust": "verified", "author": "The Esoteric Path", "desc": "ATTEMPT I (v1.12.0, council wave-5 recipe): author the NO-PANEL world lens each frame before PASS1 -- in the existing widen hook (0x6FAF4302), when a panel is open set offX(0x6FBCC418)=0, ctx+0x04(draw_left)=0, ctx+0x0C(draw_right)=DispW, dirty|=1; ScreenOpenMode left TRUE (culling+UI live). Grounded: the panel handler 0x6FB5AEC0 writes ONLY offX+mode from DisplayWidth (no separate wall global), so this run also DIAGNOSES OQ.walls_shift_source. OUTCOMES: (a) floor+walls+units all un-shift (character/waypoint bisected by panel) => walls' source IS the ctx, blocker closed; (b) floor+units un-shift but walls stay => walls recompute in PASS2 (0x6FB3B110) => name that next; (c) clicks coherent? (offX=0 persistent should self-solve per m1/m2); (d) x>=640 goes black => D2DX SurfaceIdTracker retag confirmed = the 2nd knob (m2). ==> RESULT (v1.12.0, WIN): [NOSHIFT] fired once (offX -320->0, ctxL -320->0, ctxR->1280) and HELD every frame (offX 0->0). The WORLD UN-SHIFTED -- character/waypoint bisected by the panel, walls came with it, clicks fine. Geometry reaches the dead zone (probe band[960,1280)=66-104, TILEBAND max=1277). TWO residuals remain: (1) the dead zone is still BLACK = the D2DX retag (m2's 2nd knob); (2) 1-2 FLOOR sub-layers still shift (a source our ctx authoring doesn't cover). The multi-source shift is otherwise SOLVED by authoring the no-panel lens each frame.", "refs": ["reframe.one_cause_view_state", "OQ.walls_shift_source", "finding.offx_read_173_one_write", "council.wave5_view_state_authorship", "council.wave5_d2dx_retag_is_the_black", "struct.D2Client_RenderContext"]} {"id": "OQ.floor_sublayer_residual", "kind": "openquestion", "status": "open", "trust": "verified", "author": "The Esoteric Path", "desc": "v1.12.0: after authoring the no-panel lens (offX=0/ctxL=0/ctxR=DispW each frame), the WORLD, WALLS and UNITS un-shift correctly -- but 1-2 FLOOR sub-layers still sit at the shifted position. So a floor sub-layer projects through a source our per-frame ctx authoring does NOT cover (a cached projection, a pre-PASS1 draw, or an offX re-read in the tilesub/floor-sublayer path 0x6FAF4307). Minor visual residual. Find via which draw path emits the lagging layer. Polish -- lower priority than the black. ==> IDENTIFIED (v1.12.2): it's the play-area rect playAreaW (0x6FBA9E14) -- the floor draws into it AND the hit-test reads it; narrowed to ~640 on panel-open (EP's 2022 HOM/4-tile-buffer notes). Authoring playAreaW=DispW/frame is the test. ==> v1.12.3: nViewXOffset was ALREADY 0 at our pre-PASS1 hook (no-op) -> the floor shift is COMPUTED INSIDE PASS1, not a pre-authorable global. See [[finding.floor_shift_internal_to_pass1]]. Council consult queued. ==> v1.12.6 [PROBE glidevtx count=0 @0xBEFC]: 0xBEFC is NOT the floor's live submit path. The floor's actual grDraw site is unidentified. See [[finding.floor_shift_ledger]]. Next = unfiltered return-addr logger.", "refs": ["attempt.I_noshift_lens", "struct.D2Client_RenderContext"]} {"id": "OQ.d2dx_retag_black", "kind": "openquestion", "status": "testing", "trust": "verified", "author": "The Esoteric Path", "desc": "THE LAST BARRIER TO ZERO BLACK: with the world un-shifted, floor geometry reaches x>=640 (probe band[960,1280)=66-104) and D2DX renders it BLACK. Confirmed m2's prediction: D2DX SurfaceIdTracker retags world batches with minx>=gameSize/2(=640) as USER_INTERFACE while ScreenOpenMode&1 -> the UI projection drops the world verts. Fix (council m2): runtime hot-patch the minx>=640 retag compare in glide3x during the world draw, restore after. We CANNOT rebuild D2DX. First step: read the D2DX source (bolrog/d2dx SurfaceIdTracker.cpp) to nail whether the retag drops COLOR or only writes metadata (m5 disputed) -> then locate + hot-patch it. ==> CORRECTED 2026-07-13 (read D2DX source): the surfaceId retag is METADATA ONLY (SetSurfaceId on vertices, for AA/motion) -- it does NOT relocate color (m5/chat was right, m2 wrong). The real clip is D2DX RenderContext::UpdateViewport, which sets the game VIEWPORT + SCISSOR to _gameSize.width (=960 for our desktop). World pixels x in [960,1280] are scissored -> black. FIX = widen _gameSize to 1280 via SetCustomResolution (our feature_d2dx.c / D2DXWiden). It failed alone earlier ONLY because the world was still SHIFTED (geometry never reached [960,1280]); with v1.12.0 no-shift the world fills [0,1280], so no-shift + D2DXWiden TOGETHER should fill the dead zone. RT is >=1024 (max(1024,w)); if a thin [1024,1280] band stays black, the RT alloc is the next tweak.", "refs": ["attempt.I_noshift_lens", "finding.clip_is_d2dx_drop_confirmed", "council.wave5_d2dx_retag_is_the_black", "council.wave4_gem_retag"]} {"id": "finding.playarea_governs_floor_and_hittest", "kind": "finding", "status": "testing", "trust": "trusted", "author": "Esoteric Path (Doug, 2022 notes) + Necrolis + Mir Drualga (phrozen_code Discord)", "desc": "THE FLOOR + THE MOUSE HIT-TEST are governed by the SAME play-area rect: playAreaW (0x6FBA9E14, RVA 0xF9E14) / playAreaH (0x6FBA9E18), narrowed to ~640 on panel-open. This is the '4-tile buffer'/Hall-of-Mirrors region: the world isn't rendered there by default. SOURCES (all trusted): EP's own d2-re-reference v0.8 note (playAreaW view struct, 'same rect governs mouse hit-test -> the non-clickable black') + our diag.c RD(0xF9E14); phrozen_code Discord 2022-11 -- Necrolis: 'd2dx might be doing it via a clipping rect' (= the RenderContext viewport/scissor we re-found); Mir Drualga (SGD2FreeRes author): 'those black rects are hardcoded in SGD2FreeRes to hide the HOM from not adding assets'; EP: 'a 4 tile buffer... also appears on the left if you open the character stats pane'. FIX (v1.12.2): author playAreaW=DispW each frame -- the bottom-void fix on the horizontal axis. Should make the floor cover the dead zone AND make click-to-move work standing still (currently only works while moving).", "refs": ["OQ.floor_sublayer_residual", "attempt.I_noshift_lens", "OQ.d2dx_retag_black", "struct.D2Client_RenderContext"]} {"id": "finding.floor_shift_internal_to_pass1", "kind": "finding", "status": "confirmed", "trust": "verified", "author": "The Esoteric Path", "desc": "THE FLOOR SHIFT IS INTERNAL TO PASS1 (0x6FB3B0C0), not a pre-authorable global. Authoring the no-panel lens each frame BEFORE PASS1 (offX=0, ctxL=0, ctxR=DispW) un-shifts WALLS + UNITS perfectly (they read ctxL) but the FLOOR still shifts. Ruled out, each a NO-OP at our pre-PASS1 hook: playAreaW(0x6FBA9E14)=already 1280; nViewXOffset(D2FloorTileParamsStrc 0x6FB9A9CC, EP's 'terrain shift')=already 0 ([FLOORPARAMS] never fired). Yet the floor is ISSUED full-width (TILEBAND tiles reach screenX 1278, 637 in [960,1280)) -- so it's drawn wide but at the SHIFTED position. The floor-flush projection we RE'd (screenX=ctx+0x04 - ctx+0x24 + tileAbsX) SHOULD use our ctxL=0; since the floor is shifted anyway, the FLOOR uses a different scroll/offset OR its collected tileAbsX carry the shift. Candidate: the DrawGame scratch scroll (0x6FBA9F60/5C) the passes overwrite. Need to hook INSIDE PASS1 or find the floor's internal horizontal source.", "refs": ["attempt.I_noshift_lens", "finding.playarea_governs_floor_and_hittest", "OQ.floor_sublayer_residual", "struct.D2Client_RenderContext"]} {"id": "ref.discord_corpus", "kind": "reference", "status": "noted", "trust": "trusted", "author": "The Esoteric Path", "desc": "THE DISCORD CORPUS: research/kb/corpus/discord/phrozen_code_channel.json = 52,604 messages from PhrozenKeep's #phrozen_code. Top authors (all TRUSTED-tier candidates): Necrolis(6737), Lectem(2883), whist(1930), Kingpin(1495), Firehawk, Silvermane, Ogodei, eezstreet, Mir Drualga(SGD2FreeRes author). DOUG IS IN IT as 'Esoteric Path' (47 msgs, 2022-06 to 2025-06). His 2022-11 thread IS this exact problem: he asked how to fill the 47px bottom void; Necrolis: 'd2dx might be doing it via a clipping rect' (= the RenderContext viewport we re-found); Mir: 'those black rects are hardcoded in SGD2FreeRes to hide the HOM from not adding assets'; EP: 'a 4 tile buffer... also appears on the left if you open the character stats pane'. The bottom void + the side-panel void are the same phenomenon, documented by Doug in 2022. whist = Doug's 'whilst'.", "refs": ["finding.playarea_governs_floor_and_hittest", "finding.clip_is_d2dx_drop_confirmed"]} {"id": "council.wave6_floor_hook_too_late", "kind": "finding", "status": "testing", "trust": "trusted", "author": "council wave-6 (chat m1, gem m2, clau m4)", "desc": "CONVERGENCE: the floor's shift is applied at a point our PASS1-call hook (0x6FAF4302) MISSES -- we zero the globals AFTER the floor grabbed the shifted value. Candidates: (m4/clau) the floor SNAPSHOTS the scratch scroll at the DrawGame prologue (0x6FAF42E0 mov[0x6FBA9F60],ecx / 0x6FAF42E6 mov[0x6FBA9F5C],edx from ctx, at the TOP of DrawGame, before our hook) OR bakes the shift into tileAbsX at room COLLECTION (tilesub pre-projects); (m2/gem) the floor's D2Gfx draw-offset (ctx+0x04) is set early via D2Gfx_SetDrawOffset before our hook -> hook HIGHER; (m1/chat) the floor submits the CORRECT unshifted X and D2Glide applies -DispW/4 INTERNALLY via its nScreenPanels arg in the live drawer 0x6F856840 -> force nScreenPanels=0 for the floor path. DECISIVE delta (m1): track one floor tile's submittedX (D2Client) vs vertexX (D2Glide) panel-open vs closed -- clientDelta=-320 => upstream (D2Client); glideDelta=-320 => D2Glide. v1.12.4 tests the scratch-scroll hypothesis (author 0x6FBA9F60/5C = ctx + log the delta). UNIFYING PIN (m4): both the floor AND the click are a value = DispW-320 that our hook doesn't reach; one resolution-differential scan collects EVERY DispW-320 address.", "refs": ["finding.floor_shift_internal_to_pass1", "OQ.floor_sublayer_residual", "OQ.d2dx_retag_black"]} {"id": "council.wave6_menu_and_click_answers", "kind": "finding", "status": "noted", "trust": "trusted", "author": "council wave-6 (gem m2, clau m4)", "desc": "TWO side-answers for later. (1) MENU shrink from SetCustomResolution(1280): no native menu-exclusion; scope it DYNAMICALLY by D2 client state -- hook the game-enter/exit (state 0x01 menu / 0x03 in-game) and toggle SetCustomResolution(800 menu / 1280 in-game), or gate it in the top-level render dispatch. (2) CLICK-into-black-only-while-moving (m4): it's the click-to-move path-VALIDITY / acceptance rect, a separate rect derived from DispW-320, refreshed only by motion (stale when standing still). Fix: widen the acceptance rect (find via the resolution-differential DispW-320 scan); if clicks then register but won't path, force the walkable-region refresh independent of motion.", "refs": ["council.wave6_floor_hook_too_late", "OQ.floor_sublayer_residual"]} {"id": "council.wave6b_d2dx_motion_prediction", "kind": "finding", "status": "testing", "trust": "trusted", "author": "council wave-6b (chat m10, gem m11, clau m12)", "desc": "NEW LEADING THEORY (m10, corroborated by m12): the floor/roof shift is a D2DX POST-SUBMIT bug, not a D2Client origin. (1) D2DX SurfaceIdTracker retags world batches with minx>=gameSize.w/2(=640) as USER_INTERFACE when a panel is open. (2) In OnBufferSwap, D2DX applies the player MOTION-PREDICTION offset ONLY to surfaceId!=UI && cat!=Player -- so the UI-mislabeled floor/roof batches SKIP the camera offset while the walls get it -> they slide apart AS the prediction changes with click-to-move = 'follows the mouse'. Isolated batches (the palace doorway) most susceptible. Ruled out upstream: offX held 0, floor still shifts (D2Client camera not the source). m12: the mouse-tracking PROVES live-read (not baked at collection); the black split MIRRORS sides with the panel = a compositing/retag split, not a clip. DEFINITIVE TEST (m10): d2dx.cfg [optouts] nomotionprediction=true -> if the slide stops, confirmed. FIX (m10, keeps motion pred): in the grDrawVertexArrayContiguous hook, temporarily set ScreenOpenMode(0x6FBCC414)=0 for WORLD-TILE calls only (filter by return addr: D2Glide+0xBEFC DrawFloor, +0x67AB/+0x67B9 DrawWall1/2), restore after -> D2DX won't retag the floor as UI. Start with +0xBEFC.", "refs": ["finding.floor_shift_internal_to_pass1", "OQ.floor_sublayer_residual", "finding.clip_is_d2dx_drop_confirmed", "OQ.d2dx_retag_black"]} {"id": "finding.floor_vs_wall_grdraw_sites", "kind": "finding", "status": "confirmed", "trust": "verified", "author": "The Esoteric Path (verified) + chat (council)", "desc": "THE FLOOR AND WALLS SUBMIT FROM DIFFERENT D2Glide CALL SITES (verified via disasm of the call to the grDraw wrapper 0x6F856026): DrawFloor -> 0x6F85BEF7 call (return 0x6F85BEFC = D2Glide+0xBEFC); DrawWall1 -> 0x6F8567A6 (return 0x67AB); DrawWall2 -> 0x6F8567B4 (return 0x67B9). Our glidevtx probe was filtering return-addrs [0x6840..0x6B40] = the WALL calls, so all our floor-drawer RE + the FloorCompX seam-compensation were hitting the WALLS, not the floor -- which is exactly what Doug saw (the correctly-placed tiles moving by +320). CORRECT floor filter = 0xBEFC. chat's public-1.13c-table mapping (DrawWall1/2=0x67AB/0x67B9, DrawFloor=0xBEFC) is CONFIRMED for our build. v1.12.6 + INI: glidevtx arg=0xBEFC, FloorCompX=320 -> compensate the FLOOR at its seam.", "refs": ["finding.floor_shift_internal_to_pass1", "council.wave6b_d2dx_motion_prediction", "OQ.floor_sublayer_residual"]} {"id": "protocol.evidence_rule", "kind": "reference", "status": "noted", "trust": "verified", "author": "The Esoteric Path (Doug directive 2026-07-13)", "desc": "DOCUMENTATION RIGOR RULE: every recorded observation MUST carry a valid way to confirm it -- the DLL VERSION it was seen in + the exact LOG line (or disasm) that proves it. Mark PROVEN (log/disasm) vs INFERRED (visual). No narrative claims without a verification handle. Applies to all esoteric.dll findings henceforth."} {"id": "finding.floor_shift_ledger", "kind": "finding", "status": "open", "trust": "verified", "author": "The Esoteric Path", "desc": "FLOOR+ROOF SHIFT LEDGER (evidence-backed; walls+units are FIXED, floor+roof still shift when a panel opens). Each source RULED OUT with version+log:\n* WALLS/UNITS fixed: v1.12.0 authoring no-panel lens (offX=0/ctxL=0/ctxR=DispW) pre-PASS1. PROVEN: [NOSHIFT] log fires each frame + visual (walls/units snap into place).\n* offX (0x6FBCC418): RULED OUT v1.12.5. PROVEN: [SHIFT] 'offX 0->0' held every frame, floor STILL shifted.\n* playAreaW (0x6FBA9E14): RULED OUT v1.12.2. PROVEN: [NOSHIFT] 'playAreaW 1280->1280' (already full, no-op).\n* nViewXOffset (D2FloorTileParamsStrc 0x6FB9A9CC): RULED OUT v1.12.3. PROVEN: [FLOORPARAMS] NEVER logged (condition fvx!=0 false -> already 0 at our hook).\n* scratch scroll (0x6FBA9F60/5C): RULED OUT v1.12.4. PROVEN: [SCRATCH] NEVER logged (already == ctx scroll).\n* D2Glide drawer 0x856840 vertex math: RULED OUT by DISASM -- vertexX = baseX + subtileX; the 640 midpoint feeds ONLY the cull bounds ([esp+0x30]/[esp+0x38], already NOP'd), no -DispW/4 on the vertex.\n* D2DX motion prediction: RULED OUT -- d2dx.cfg nomotionprediction=true -> no change (Doug); + the shift is STATIC not dynamic (Doug correction), which motion-prediction wouldn't produce.\n* grDraw site 0xBEFC (chat's 'DrawFloor'): RULED OUT v1.12.6. PROVEN: [PROBE glidevtx] arg=0xBEFC -> count=0 (0 hits). 0x6F85BEF7 IS a call site on disk but is NOT on the live floor path in our build.\nVERIFIED-live: WALLS submit via grDraw returns 0x67AB/0x67B9 (disasm: 0x6F8567A6/B4 call the wrapper 0x856026; probe with arg=0x6840 fired in v1.11-1.12.5). 0x6840==walls is INFERRED (Doug: compensating that filter moved the CORRECTLY-placed tiles) + chat labels them DrawWall1/2.\nOPEN: the FLOOR's actual LIVE grDraw return address is UNIDENTIFIED (not 0x6840=walls, not 0xBEFC=count0). RIGOROUS NEXT: an UNFILTERED return-address logger (probe arg=0) that dumps every distinct grDraw return addr + its vertex-X range + count -> identify the floor by its signature, THEN compensate/fix that exact site.", "refs": ["finding.floor_vs_wall_grdraw_sites", "finding.floor_shift_internal_to_pass1", "OQ.floor_sublayer_residual", "protocol.evidence_rule"]} {"id": "council.wave7_grdraw_seam_delta", "kind": "finding", "status": "testing", "trust": "trusted", "author": "council wave-7 (chat, gem, clau)", "desc": "CONVERGENCE: measure the floor batch's vertex X at the grDraw seam, panel-CLOSED vs panel-OPEN. dMinX=-320 => D2Client submits the floor shifted (UPSTREAM); dMinX=0 => D2DX shifts it (DOWNSTREAM). Also capture the caller return-addr to NAME the floor's live site (our 0xBEFC guess fired 0x). chat: D2DX's 0xBEFC 'DrawFloor' is only an IdentifyGameAddress label, not the live path; forward is unchanged (OnDrawVertexArrayContiguous copies x/y verbatim). gem: if downstream, read D2DX's VS projection matrix via a D3D11 VSSetConstantBuffers vtable hook (matrix[12]=X translation). clau: DISSENT-then-agree -- 'mouse kills it' argument uses the RETRACTED mouse-tracking premise (Doug corrected to STATIC), so its mouse-sweep isn't our discriminator; BUT clau's mouse-INDEPENDENT argument is strong: walls render correct through the SAME D2DX pipeline, so if D2DX shifted world batches walls would shift too -> predicts dMinX=-320 (client-side). clau CAUTION taken: do NOT do the ScreenOpenMode=0 mask (attempt-A anti-pattern: fixes readers who look, misses others, desyncs hit-test). IMPLEMENTED v1.12.7 [Probes] Survey=1 + glidevtx arg=0 -> [SURVEY] rows per caller, closed vs open.", "refs": ["finding.floor_shift_ledger", "finding.floor_vs_wall_grdraw_sites", "protocol.evidence_rule"]} {"id": "finding.live_grdraw_callers", "kind": "finding", "status": "open", "trust": "verified", "author": "The Esoteric Path (v1.12.8 [SURVEY])", "desc": "THE LIVE grDraw CALLERS (v1.12.8 Survey, panel-CLOSED only so far): D2Glide+0x6A55 (n=87710, x=-32..1296, the dense one), 0xA344 (n=16767, x=0..1151), 0xA555 (n=5340, x=303..1152), 0x704A (n=895, x=1216..1296), 0x9AF4 (n=293, x=11..788). CORRECTION (rigor): finding.floor_vs_wall_grdraw_sites claimed walls=0x67AB/0x67B9 (from disasm of call sites 0x6F8567A6/B4) -- but those return-addrs DO NOT APPEAR in the survey, so they do NOT fire on the live path. The disasm found call sites that aren't reached. The REAL callers are the 5 above. Still OPEN: which is the FLOOR (need panel-OPEN data -> the caller with dMinX~-320). v1.12.8's run was the menu run (open[n=0] everywhere); a park+toggle run is needed. NOTE the survey only counts IN-GAME frames (eso_probe_frame runs from the DrawGame hook, not at the menu).", "refs": ["finding.floor_shift_ledger", "finding.floor_vs_wall_grdraw_sites", "council.wave7_grdraw_seam_delta", "protocol.evidence_rule"]} {"id": "finding.menu_worldctx_gate", "kind": "finding", "status": "confirmed", "trust": "verified", "author": "The Esoteric Path (v1.12.9 [D2DXWiden] log)", "desc": "MENU FIX. v1.12.9 grSstWinOpen log: the IN-GAME open = res=4099(0x1003) with worldCtx=0x214439AC (NON-NULL); the MENU opens = res=7 and res=4097 with worldCtx=NULL. The world render ctx (*0x6FBCC3C4) is set at the in-game open and null at the menu -> gate is worldCtx!=null. FIX v1.13.0: eso_d2dx_set_wide calls SetCustomResolution(1280) only when worldCtx!=null -> menu keeps native size, in-game world stays widened. (grSstWinOpen arg1=window handle; the resolution is arg2=[esp+0x2C].)", "refs": ["OQ.d2dx_retag_black"]} {"id": "finding.survey_floor_is_downstream", "kind": "finding", "status": "testing", "trust": "verified", "author": "The Esoteric Path (v1.12.9 [SURVEY] open data)", "desc": "SURPRISE: the floor shift is likely DOWNSTREAM in D2DX, not at the D2Client->grDraw submit. Survey open-vs-closed, 5 live callers: 0x6A55 (floor, n=828558, closed x=-32..1311 / open x=-32..1296 => dMinX=0, dMaxX~-15: STABLE, NOT shifted at submit); 0x09AF4 (dead-zone FILL, open x=640..1280 n=22082 = the world we enabled behind the panel, WORKING); 0xA555 (dMinX=-84); 0xA344 (dMinX=33); 0x704A (dMinX=16). NO CALLER submits shifted by -320. So the floor is submitted un-shifted and D2DX shifts it downstream => chat/gem's branch, AGAINST clau's client-side prediction (reconciled: D2DX shifts only floor-category batches, not walls). CAVEAT: aggregate min/max is confounded by the changing tile set on open, but the ABSENCE of any -320 across all 5 callers is robust. nomotionprediction=true gave no change, so it's a D2DX transform OTHER than motion-prediction. NEXT: specific-tile track OR gem's D3D11 VSSetConstantBuffers matrix read.", "refs": ["council.wave7_grdraw_seam_delta", "finding.live_grdraw_callers", "finding.floor_shift_ledger", "protocol.evidence_rule"]} {"id": "ext.D2Client.ScreenShiftX", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2Client.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "Horizontal screen shift (viewport pan offset). Named exactly in FOCUS. | src: D2Client.dll\tScreenShiftX\tOffset\t0x11B9A0", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "rva": "0x11b9a0"} {"id": "ext.D2Client.ScreenShiftY", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2Client.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "Vertical screen shift (viewport pan offset). Named exactly in FOCUS. | src: D2Client.dll\tScreenShiftY\tOffset\t0x11B9A4", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "rva": "0x11b9a4"} {"id": "ext.D2Client.GeneralDisplayHeight", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2Client.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "General display height. Named exactly in FOCUS. | src: D2Client.dll\tGeneralDisplayHeight\tOffset\t0xDBC4C", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "rva": "0xdbc4c"} {"id": "ext.D2Client.IsAutomapOpen", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2Client.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "Automap open flag. | src: D2Client.dll\tIsAutomapOpen\tOffset\t0xFADA8", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "rva": "0xfada8"} {"id": "ext.D2Client.IsGameMenuOpen", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2Client.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "Game menu open flag. | src: D2Client.dll\tIsGameMenuOpen\tOffset\t0xFADA4", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "rva": "0xfada4"} {"id": "ext.D2Client.IsHelpScreenOpen", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2Client.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "Help screen open flag. | src: D2Client.dll\tIsHelpScreenOpen\tOffset\t0xFAE04", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "rva": "0xfae04"} {"id": "ext.D2Client.InventoryArrangeMode", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2Client.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "Inventory arrange mode (UI panel layout state). | src: D2Client.dll\tInventoryArrangeMode\tOffset\t0x11B99C", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "rva": "0x11b99c"} {"id": "ext.D2Client.IsNewSkillButtonPressed", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2Client.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "New-skill button pressed flag (UI element state). | src: D2Client.dll\tIsNewSkillButtonPressed\tOffset\t0x11C30C", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "rva": "0x11c30c"} {"id": "ext.D2Client.IsNewStatsButtonPressed", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2Client.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "New-stats button pressed flag (UI element state). | src: D2Client.dll\tIsNewStatsButtonPressed\tOffset\t0x11C308", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "rva": "0x11c308"} {"id": "ext.D2Client.IngameMousePositionX", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2Client.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "In-game mouse cursor X (screen coordinate). | src: D2Client.dll\tIngameMousePositionX\tOffset\t0x11B828", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "rva": "0x11b828"} {"id": "ext.D2Client.IngameMousePositionY", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2Client.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "In-game mouse cursor Y (screen coordinate). | src: D2Client.dll\tIngameMousePositionY\tOffset\t0x11B824", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "rva": "0x11b824"} {"id": "ext.D2Client.DrawCenteredUnicodeText", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2Client.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "Draws centered unicode text on screen. | src: D2Client.dll\tDrawCenteredUnicodeText\tOffset\t0xBC4E0", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "rva": "0xbc4e0"} {"id": "ext.D2GFX.ResolutionMode", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2GFX.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "Render resolution mode selector. Comment gives enum values. | src: D2GFX.dll\tResolutionMode\tOffset\t0x11260\t0 = 640x480, 1 = Main Menu, 2 = 800x600, 3 = 1344x700", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "rva": "0x11260", "value": "0 = 640x480, 1 = Main Menu, 2 = 800x600, 3 = 1344x700"} {"id": "ext.D2GFX.VideoMode", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2GFX.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "Active video/render backend selector. Comment gives enum values. | src: D2GFX.dll\tVideoMode\tOffset\t0x11258\t1 = GDI, 2 = Software, 3 = DirectDraw, 4 = Glide, 5 = OpenGL, 6 = Direct3D, 7 = Rave", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "rva": "0x11258", "value": "1 = GDI, 2 = Software, 3 = DirectDraw, 4 = Glide, 5 = OpenGL, 6 = Direct3D, 7 = Rave"} {"id": "ext.D2GFX.IsWindowedMode", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2GFX.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "Windowed vs fullscreen flag. | src: D2GFX.dll\tIsWindowedMode\tOffset\t0x1125C", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "rva": "0x1125c"} {"id": "ext.D2GFX.WindowHandle", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2GFX.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "HWND of the render window. | src: D2GFX.dll\tWindowHandle\tOffset\t0x11264\tgtGfxSystem.hWnd", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "rva": "0x11264", "value": "gtGfxSystem.hWnd"} {"id": "ext.D2GFX.DrawCelContext", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2GFX.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "Draws a CEL (sprite) via graphics context — core sprite/cell blit entry point. | src: D2GFX.dll\tDrawCelContext\tOrdinal\t10041", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "locator": "D2GFX.dll ord 10041"} {"id": "ext.D2GFX.DrawRectangle", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2GFX.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "Draws a rectangle primitive. Named in FOCUS. | src: D2GFX.dll\tDrawRectangle\tOrdinal\t10014", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "locator": "D2GFX.dll ord 10014"} {"id": "ext.D2DDraw.D2DDraw_DisplayWidth", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2DDraw.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "DirectDraw backend display width. | src: D2DDraw.dll\tDisplayWidth\tOffset\t0x101D4", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "rva": "0x101d4"} {"id": "ext.D2DDraw.D2DDraw_DisplayHeight", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2DDraw.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "DirectDraw backend display height. | src: D2DDraw.dll\tDisplayHeight\tOffset\t0x101CC", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "rva": "0x101cc"} {"id": "ext.D2DDraw.D2DDraw_BitBlockWidth", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2DDraw.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "DirectDraw bit-block (blit) width. | src: D2DDraw.dll\tBitBlockWidth\tOffset\t0x101C8", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "rva": "0x101c8"} {"id": "ext.D2DDraw.D2DDraw_BitBlockHeight", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2DDraw.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "DirectDraw bit-block (blit) height. | src: D2DDraw.dll\tBitBlockHeight\tOffset\t0x101D8", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "rva": "0x101d8"} {"id": "ext.D2DDraw.D2DDraw_CelDisplayLeft", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2DDraw.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "DirectDraw CEL display left bound. | src: D2DDraw.dll\tCelDisplayLeft\tOffset\t0x101E8", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "rva": "0x101e8"} {"id": "ext.D2DDraw.D2DDraw_CelDisplayRight", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2DDraw.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "DirectDraw CEL display right bound. | src: D2DDraw.dll\tCelDisplayRight\tOffset\t0x101EC", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "rva": "0x101ec"} {"id": "ext.D2GDI.D2GDI_BitBlockWidth", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2GDI.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "GDI backend bit-block (blit) width. | src: D2GDI.dll\tBitBlockWidth\tOffset\t0xCA80", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "rva": "0xca80"} {"id": "ext.D2GDI.D2GDI_BitBlockHeight", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2GDI.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "GDI backend bit-block (blit) height. | src: D2GDI.dll\tBitBlockHeight\tOffset\t0xCA90", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "rva": "0xca90"} {"id": "ext.D2GDI.D2GDI_CelDisplayLeft", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2GDI.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "GDI CEL display left bound. | src: D2GDI.dll\tCelDisplayLeft\tOffset\t0xCA98", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "rva": "0xca98"} {"id": "ext.D2GDI.D2GDI_CelDisplayRight", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2GDI.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "GDI CEL display right bound. | src: D2GDI.dll\tCelDisplayRight\tOffset\t0xCA9C", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "rva": "0xca9c"} {"id": "ext.D2Direct3D.D2Direct3D_DisplayWidth", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2Direct3D.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "Direct3D backend display width. | src: D2Direct3D.dll\tDisplayWidth\tOffset\t0x1AB44", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "rva": "0x1ab44"} {"id": "ext.D2Direct3D.D2Direct3D_DisplayHeight", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2Direct3D.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "Direct3D backend display height. | src: D2Direct3D.dll\tDisplayHeight\tOffset\t0x1AFD4", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "rva": "0x1afd4"} {"id": "ext.D2Win.DrawUnicodeText", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2Win.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "Draws unicode text. | src: D2Win.dll\tDrawUnicodeText\tOrdinal\t10150", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "locator": "D2Win.dll ord 10150"} {"id": "ext.D2Win.GetPopupUnicodeTextWidthAndHeight", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2Win.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "Measures popup text width/height (layout). | src: D2Win.dll\tGetPopupUnicodeTextWidthAndHeight\tOrdinal\t10177", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "locator": "D2Win.dll ord 10177"} {"id": "ext.D2Win.GetUnicodeTextDrawWidth", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2Win.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "Measures drawn text width (layout). | src: D2Win.dll\tGetUnicodeTextDrawWidth\tOrdinal\t10028", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "locator": "D2Win.dll ord 10028"} {"id": "ext.D2Win.GetUnicodeTextNDrawWidth", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2Win.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "Measures drawn text width for N chars (layout). | src: D2Win.dll\tGetUnicodeTextNDrawWidth\tOrdinal\t10055", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "locator": "D2Win.dll ord 10055"} {"id": "ext.D2Win.SetPopUpUnicodeText", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2Win.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "Sets popup text content. | src: D2Win.dll\tSetPopUpUnicodeText\tOrdinal\t10085", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "locator": "D2Win.dll ord 10085"} {"id": "ext.D2Win.SetUnicodeTextFont", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2Win.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "Selects active text font for drawing. | src: D2Win.dll\tSetUnicodeTextFont\tOrdinal\t10184", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "locator": "D2Win.dll ord 10184"} {"id": "ext.D2Win.LoadCelFile", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2Win.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "Loads a CEL sprite file. | src: D2Win.dll\tLoadCelFile\tOrdinal\t10111", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "locator": "D2Win.dll ord 10111"} {"id": "ext.D2Win.UnloadCelFile", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2Win.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "Unloads a CEL sprite file. | src: D2Win.dll\tUnloadCelFile\tOrdinal\t10126", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "locator": "D2Win.dll ord 10126"} {"id": "ext.D2Win.MainMenuMousePositionX", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2Win.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "Main-menu mouse cursor X (screen coordinate). | src: D2Win.dll\tMainMenuMousePositionX\tOffset\t0x21488", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "rva": "0x21488"} {"id": "ext.D2Win.MainMenuMousePositionY", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2Win.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "Main-menu mouse cursor Y (screen coordinate). | src: D2Win.dll\tMainMenuMousePositionY\tOffset\t0x2148C", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "rva": "0x2148c"} {"id": "ext.D2CMP.GetCelFromCelContext", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2CMP.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "Retrieves a CEL frame from a CEL context (sprite frame access). | src: D2CMP.dll\tGetCelFromCelContext\tOrdinal\t10021", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "locator": "D2CMP.dll ord 10021"} {"id": "ext.D2CMP.CloseCelFile", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2CMP.dll", "author": "mir (Diablo-II-Address-Table, public domain)", "desc": "Closes a CEL file (sprite resource cleanup). | src: D2CMP.dll\tCloseCelFile\tOrdinal\t10065", "source": ["https://raw.githubusercontent.com/mir-diablo-ii-tools/Diablo-II-Address-Table/master/1.13C.txt"], "locator": "D2CMP.dll ord 10065"} {"id": "ext.(global).Target_resolution", "kind": "note", "status": "sourced", "trust": "trusted", "module": "(global)", "author": "IAmTrial (SlashWork d2widescreenhack)", "desc": "Hack replaces 640x480 mode with 1066x600 true 16:9. 0x280=640, 0x1E0=480, 0x42A=1066, 0x258=600. Note width 1066=0x42A but render uses 1064=0x428 in one spot (see D2gdi Part1). | src: replacing 640x480 mode; height wouldn't change, width would, true 16:9", "source": ["https://raw.githubusercontent.com/IAmTrial/SlashWork/master/d2widescreenhack.md"], "locator": "1066x600", "value": "640->1066 (0x280->0x42A), 480->600 (0x1E0->0x258)"} {"id": "ext.D2gfx.D2gfx_dll_window_resize_width_height", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2gfx.dll", "author": "IAmTrial (SlashWork d2widescreenhack)", "desc": "Resizes the game window on resolution change. Sets screen width [eax] then screen height [ecx]. Left unmodified: game crunches elements, mouse cannot move past 640th x / 480th y, black lines. RENDER/window sizing. | src: ORIG: C7 00 80020000 mov [eax],00000280 (640 screen width); C7 01 E0010000 mov [ecx],000001E0 (480 screen height). PATCH: C7 00 2A040000 mov [eax],0000042A (1066); C7 01 5802000", "source": ["https://raw.githubusercontent.com/IAmTrial/SlashWork/master/d2widescreenhack.md"], "rva": "0x7fe8", "value": "width->0x42A(1066), height->0x258(600)"} {"id": "ext.D2gdi.D2gdi_dll_Part_1_game_width_height_RENDER", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2gdi.dll", "author": "IAmTrial (SlashWork d2widescreenhack)", "desc": "Sets values determining how D2 renders the game (width render into esi, height render into edx). Unaltered: stretches 640x480 to fill window then crashes. WIDTH RENDER USES 1064 (0x428) NOT 1066 — author: non-multiple-of-4 width overflows onto LEFT side of screen. Height render 600. | src: ORIG: BE 80020000 mov esi,00000280 (640 game's width render); BE E0010000 mov edx,000001E0 (480 height render). PATCH: BE 28040000 mov esi,00000428 (1064 width render); BE 58020000", "source": ["https://raw.githubusercontent.com/IAmTrial/SlashWork/master/d2widescreenhack.md"], "rva": "0x6d55", "value": "width render->0x428(1064), height render->0x258(600)"} {"id": "ext.D2gdi.D2gdi_dll_Part_2_x_position_render_cutoff", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2gdi.dll", "author": "IAmTrial (SlashWork d2widescreenhack)", "desc": "Sets x-position where D2 should STOP rendering entities (walls, pillars). Unmodified: anything past x=640 not rendered (or incorrectly); no crash. Write target [D2gdi.dll+0xCA9C]. RENDER BOUNDARY. | src: ORIG: C7 05 9CCA876F 80020000 mov [D2gdi.dll+0xCA9C],00000280 (640, x-pos stop rendering). PATCH: C7 05 9CCA876F 2A040000 mov [D2gdi.dll+0xCA9C],0000042A (1066)", "source": ["https://raw.githubusercontent.com/IAmTrial/SlashWork/master/d2widescreenhack.md"], "rva": "0x706b", "value": "x-cutoff->0x42A(1066)"} {"id": "ext.D2client.D2Client_dll_Part_1_FOV_width_height_logic", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2client.dll", "author": "IAmTrial (SlashWork d2widescreenhack)", "desc": "THE 0x10E29 BLOCK. Sets D2 field-of-vision, character/map positioning, and UI element positions. mov eax,0x280 then stores eax to [D2client+0xDBC48] (width logic), then mov [D2client+0xDBC4C],0x1E0 (height logic). Unmodified: renders as 640x480 and places game at upper-left of window. The width store (A3 48BCB86F) is left UNMODIFIED; only the eax immediate (640->1066) and the height DWORD (480->600) change. | src: ORIG: B8 80020000 mov eax,00000280 (640); A3 48BCB86F mov [D2client.dll+0xDBC48],eax (width logic); C7 05 4CBCB86F E0010000 mov [D2client.dll+0xDBC4C],000001E0 (480 height logic). ", "source": ["https://raw.githubusercontent.com/IAmTrial/SlashWork/master/d2widescreenhack.md"], "rva": "0x10e29", "value": "eax 0x280->0x42A(1066); [+0xDBC48]=width; [+0xDBC4C] 0x1E0->0x258(600)"} {"id": "ext.D2client.D2client_dll_0xDBC4C_game_height_logic", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2client.dll", "author": "IAmTrial (SlashWork d2widescreenhack)", "desc": "Memory location storing the game's logic height. Written directly as DWORD constant in the 0x10E29 block. | src: C7 05 4CBCB86F 58020000 mov [D2client.dll+0xDBC4C], 00000258 ; 600 height logic", "source": ["https://raw.githubusercontent.com/IAmTrial/SlashWork/master/d2widescreenhack.md"], "rva": "0xdbc4c", "value": "0x1E0(480) -> 0x258(600)"} {"id": "ext.D2client.D2Client_dll_Part_2_UI_panel_offset_table_orig", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2client.dll", "author": "IAmTrial (SlashWork d2widescreenhack)", "desc": "THE 0xC3A11 UI-PANEL OFFSET SITE. Original 640x480-mode panel placement: writes ebx (=0) into panel x-offset [+0x11B9A0] and y-offset [+0x11B9A4]. Governs alignment of quest buttons, waypoint buttons, mercenary stats. reg->mem is fewer bytes than DWORD-const->mem, so 8 extra bytes needed to inject HD constants. | src: 89 1D A0B9BC6F mov [D2client.dll+0x11B9A0],ebx (x-offset of panels, ebx=0); 89 1D A4B9BC6F mov [D2client.dll+0x11B9A4],ebx (y-offset of panels, ebx=0)", "source": ["https://raw.githubusercontent.com/IAmTrial/SlashWork/master/d2widescreenhack.md"], "rva": "0xc3a11", "value": "x-offset [+0x11B9A0]=0(ebx), y-offset [+0x11B9A4]=0(ebx)"} {"id": "ext.D2client.D2client_dll_0x11B9A0_panel_X_offset", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2client.dll", "author": "IAmTrial (SlashWork d2widescreenhack)", "desc": "Memory storing X-offset positioning of UI panels. 640x480 -> 0; 800x600 -> 0x50 (80); 1066x600 -> 0xD5 (213). Written via 89 1D A0B9BC6F (reg) or C7 05 A0B9BC6F (const). | src: stores the x-offset positioning of panels; 1066x600 value 000000D5 (213)", "source": ["https://raw.githubusercontent.com/IAmTrial/SlashWork/master/d2widescreenhack.md"], "rva": "0x11b9a0", "value": "640:0 / 800:0x50(80) / 1066:0xD5(213)"} {"id": "ext.D2client.D2client_dll_0x11B9A4_panel_Y_offset", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2client.dll", "author": "IAmTrial (SlashWork d2widescreenhack)", "desc": "Memory storing Y-offset positioning of UI panels. 640x480 -> 0; 800x600 AND 1066x600 -> 0xFFFFFFC4 (-60). Because 1066x600 shares 800x600's height (600), the y-offset code for 800x600 is reused. | src: stores the y-offset positioning of panels; value FFFFFFC4 (-60)", "source": ["https://raw.githubusercontent.com/IAmTrial/SlashWork/master/d2widescreenhack.md"], "rva": "0x11b9a4", "value": "640:0 / 800 & 1066:0xFFFFFFC4(-60)"} {"id": "ext.D2client.D2Client_dll_Part_2_wider_view_w_75_16_jne_ORI", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2client.dll", "author": "IAmTrial (SlashWork d2widescreenhack)", "desc": "THE 75 16 PER-RESOLUTION BRANCH. Original: jne to 0xC3A11 (640x480 code) if not 800x600 mode. 800x600 block sets x-offset=0x50(80) and y-offset=0xFFFFFFC4(-60), then EB 0C jmp to 0xC3A1D past the 640x480 code. 640x480 block (at 0xC3A11) writes ebx(0) to both offsets. jne displacement = 0x16. | src: 75 16 jne D2client.dll+0xC3A11 (jump to 640x480 code if not 800x600); C7 05 A0B9BC6F 50000000 mov [+0x11B9A0],00000050 (80 x-offset); C7 05 A4B9BC6F C4FFFFFF mov [+0x11B9A4],FFFFF", "source": ["https://raw.githubusercontent.com/IAmTrial/SlashWork/master/d2widescreenhack.md"], "rva": "0xc39f9", "value": "jne rel8=0x16 -> target 0xC3A11; 800x600 x=0x50, y=0xFFFFFFC4"} {"id": "ext.D2client.D2Client_dll_Part_2_SOLUTION_reordered_75_0C_j", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2client.dll", "author": "IAmTrial (SlashWork d2widescreenhack)", "desc": "PATCHED per-resolution branch: author reorders so the shared y-offset store (-60) runs FIRST for both 800x600 and 1066x600 (both height 600), freeing 6 bytes and cutting needed bytes 8->4. jne displacement CHANGED from 0x16 to 0x0C. Now: write y-offset -60; jne 0xC3A11 (=1066x600 code) if not 800x600; 800x600 sets x=0x50(80); jmp past; the 0xC3A11 '1066x600 code' sets x-offset=0xD5(213); two trailing 90 NOPs (leftover bytes). CONCLUSION ON PANEL SHIFT: panel x-offset 213 for | src: C7 05 A4B9BC6F C4FFFFFF mov [+0x11B9A4],FFFFFFC4 (-60 y-offset); 75 0C jne D2client.dll+0xC3A11 (jump to 1066x600 code if not 800x600); C7 05 A0B9BC6F 50000000 mov [+0x11B9A0],0000", "source": ["https://raw.githubusercontent.com/IAmTrial/SlashWork/master/d2widescreenhack.md"], "rva": "0xc39f9", "value": "jne rel8 0x16->0x0C; 1066x600 x-offset=0xD5(213); +2 NOP(0x90)"} {"id": "ext.D2client.Author_conclusion_panel_byte_budget_600_height", "kind": "note", "status": "sourced", "trust": "trusted", "module": "D2client.dll", "author": "IAmTrial (SlashWork d2widescreenhack)", "desc": "Author's reasoning verbatim-ish: reg->mem needs fewer bytes than DWORD-const->mem, so HD mode needs 8 extra bytes; instead of call+NOP he reorders. Because height is unchanged 800x600<->1066x600, the 800x600 y-offset setup code is reused, freeing 6 bytes and reducing writes from 8 to 4 bytes. | src: 'the height remains the same when switching from 800x600 mode to 1066x600 mode... By reordering the code, I can reuse the code that sets up the y-offset positioning for 800x600 mod", "source": ["https://raw.githubusercontent.com/IAmTrial/SlashWork/master/d2widescreenhack.md"], "rva": "0xc39f9", "value": "8 extra bytes needed -> reduced to 4; 6 bytes freed"} {"id": "ext.D2glide.D2glide_dll_render_width_height", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2glide.dll", "author": "IAmTrial (SlashWork d2widescreenhack)", "desc": "Glide mode entity render dimensions. Writes rendering width [D2glide.dll+0x15A68] and height [D2glide.dll+0x15B04]. Unchanged: entities rendered at incorrect location. RENDER. | src: ORIG: C7 05 685A866F 80020000 mov [D2glide.dll+0x15A68],00000280 (width 640); C7 05 045B866F E0010000 mov [D2glide.dll+0x15B04],000001E0 (height 480). PATCH: ...2A040000 (1066); ..", "source": ["https://raw.githubusercontent.com/IAmTrial/SlashWork/master/d2widescreenhack.md"], "rva": "0xdcd5", "value": "width [+0x15A68]->0x42A(1066); height [+0x15B04]->0x258(600)"} {"id": "ext.glide3x.glide3x_dll_window_width_height", "kind": "function", "status": "sourced", "trust": "trusted", "module": "glide3x.dll", "author": "IAmTrial (SlashWork d2widescreenhack)", "desc": "Sets D2 (Glide) window size. Loads ptr [glide3x.dll+0x1C9A0] (width addr) into edx then writes 640; loads ptr [glide3x.dll+0x1C82C] (height addr) into ecx then writes 480. NOTE: Cheat-Engine relative addresses differ from hex-editor addresses (offset by 0xA00). In the printed PATCH the loader/immediate opcodes C7 02 80020000 / C7 01 E0010000 are shown unchanged but the target values in comments become 1066/600 — the immediates to actually write are 0000042A and 00000258. | src: 8B 15 A0C94100 mov edx,[glide3x.dll+0x1C9A0] (Glide window width addr); C7 02 80020000 mov [edx],00000280 (640->1066 0000042A); 8B 0D 2CC84100 mov ecx,[glide3x.dll+0x1C82C] (height", "source": ["https://raw.githubusercontent.com/IAmTrial/SlashWork/master/d2widescreenhack.md"], "rva": "0xc0d5", "value": "[+0x1C9A0]=width ptr ->1066(0x42A); [+0x1C82C]=height ptr ->600(0x258)"} {"id": "ext.glide3x.glide3x_CE_vs_hex_editor_address_divergence", "kind": "note", "status": "sourced", "trust": "trusted", "module": "glide3x.dll", "author": "IAmTrial (SlashWork d2widescreenhack)", "desc": "Author flags glide3x as hardest because Cheat Engine relative instruction addresses differ from hex-editor addresses: 0xC0D5-0xC0EC (hex editor) == 0xCAD5-0xCAEE (Cheat Engine). | src: 'relative instruction addresses that show up on Cheat Engine are not the same relative addresses that are shown in a hex editor'", "source": ["https://raw.githubusercontent.com/IAmTrial/SlashWork/master/d2widescreenhack.md"], "locator": "glide3x.dll", "value": "hexed 0xC0D5..0xC0EC = CE 0xCAD5..0xCAEE"} {"id": "ext.d2client draw_screen_background.DrawLeftScreenBackground", "kind": "function", "status": "sourced", "trust": "trusted", "module": "d2client draw_screen_background", "author": "Mir Drualga (SGD2FreeRes)", "desc": "Fills the LEFT half of the screen. First draws a solid black rectangle over the left half to block transparent-DC6 cheats, then tiles the config screen-background DC6 across it. This is the perimeter/letterbox fill on the left of the 640-wide play area. | src: ::d2::d2gfx::DrawRectangle(0, 0, resolution.width / 2, resolution.height, 0, ::d2::DrawEffect::kNone);", "source": ["https://github.com/mir-diablo-ii-tools/SlashGaming-Diablo-II-Free-Resolution"], "locator": "replacement.cpp L65-122"} {"id": "ext.d2client draw_screen_background.DrawRightScreenBackground", "kind": "function", "status": "sourced", "trust": "trusted", "module": "d2client draw_screen_background", "author": "Mir Drualga (SGD2FreeRes)", "desc": "Fills the RIGHT half of the screen. Draws a black rectangle from x=width/2 to x=width over full height, then tiles the background DC6 rightward. Left+Right together produce the full perimeter fill around the centered 640x480 UI region. | src: ::d2::d2gfx::DrawRectangle(resolution.width / 2, 0, resolution.width, resolution.height, 0, ::d2::DrawEffect::kNone);", "source": ["https://github.com/mir-diablo-ii-tools/SlashGaming-Diablo-II-Free-Resolution"], "locator": "replacement.cpp L124-180"} {"id": "ext.draw_screen_background.background_tiling_loop", "kind": "note", "status": "sourced", "trust": "trusted", "module": "draw_screen_background", "author": "Mir Drualga (SGD2FreeRes)", "desc": "Tiling loop: half_num_frames = GetNumFrames()/2; rows alternate row_start_frame = (row%2)*half_num_frames; columns drawn until width_covered reaches (width/2)-1. Left screen anchors DrawPositionXBehavior::kRight and draws from (width/2 - width_covered); right screen anchors kLeft and draws from (width/2 + width_covered). Both use position_y_behavior kTop. Row loop condition compares height_covered against resolution.width (note: width, not height — as written in source).", "source": ["https://github.com/mir-diablo-ii-tools/SlashGaming-Diablo-II-Free-Resolution"], "locator": "replacement.cpp L94-121 / L153-179"} {"id": "ext.draw_screen_background.kOriginalScreenBorderFrameImagePath", "kind": "global", "status": "sourced", "trust": "trusted", "module": "draw_screen_background", "author": "Mir Drualga (SGD2FreeRes)", "desc": "Original 800x600 border-frame DC6 path used when IsUseOriginalScreenBorderFrame() is true. | src: constexpr std::string_view kOriginalScreenBorderFrameImagePath = \"data\\\\global\\\\UI\\\\Panel\\\\800BorderFrame\";", "source": ["https://github.com/mir-diablo-ii-tools/SlashGaming-Diablo-II-Free-Resolution"], "locator": "replacement.cpp L62-63", "value": "data\\\\global\\\\UI\\\\Panel\\\\800BorderFrame"} {"id": "ext.DrawOriginalLeftScreenBorderFrame.OriginalLeftBorderFrame_centering", "kind": "note", "status": "sourced", "trust": "trusted", "module": "DrawOriginalLeftScreenBorderFrame", "author": "Mir Drualga (SGD2FreeRes)", "desc": "Centering math for the original 800-wide border frame around the 640-wide play area. left = (width-640-(800-640))/2 = (width-800)/2; top = ((height-480-(600-480))/2)-3 = ((height-600)/2)-3. This is the (width-640)/2 family of centering offsets the task references, adjusted for the 800x600 frame art. | src: const int left = (resolution.width - 640 - (800 - 640)) / 2; const int top = ((resolution.height - 480 - (600 - 480)) / 2) - 3;", "source": ["https://github.com/mir-diablo-ii-tools/SlashGaming-Diablo-II-Free-Resolution"], "locator": "replacement.cpp L193-194"} {"id": "ext.DrawOriginalRightScreenBorderFrame.OriginalRightBorderFrame_centering", "kind": "note", "status": "sourced", "trust": "trusted", "module": "DrawOriginalRightScreenBorderFrame", "author": "Mir Drualga (SGD2FreeRes)", "desc": "Right-side original border frame anchor. right = (width+640+(800-640))/2 = (width+800)/2; top same as left ((height-600)/2)-3. | src: const int right = (resolution.width + 640 + (800 - 640)) / 2; const int top = ((resolution.height - 480 - (600 - 480)) / 2) - 3;", "source": ["https://github.com/mir-diablo-ii-tools/SlashGaming-Diablo-II-Free-Resolution"], "locator": "replacement.cpp L241-242"} {"id": "ext.DrawCustomLeft/RightScreenBorderFrame.CustomBorder_screen_left_top", "kind": "note", "status": "sourced", "trust": "trusted", "module": "DrawCustomLeft/RightScreenBorderFrame", "author": "Mir Drualga (SGD2FreeRes)", "desc": "Custom border frames center the 640x480 UI: screen_left = (width-640)/2, screen_top = (height-480)/2, screen_right = (width+640)/2. Vertical centering of the side borders uses (256+176)=432 as the reference inner-panel height: border_top = screen_top + ((432 - border_height)/2). | src: const int screen_left = (resolution.width - 640) / 2; const int screen_top = (resolution.height - 480) / 2;", "source": ["https://github.com/mir-diablo-ii-tools/SlashGaming-Diablo-II-Free-Resolution"], "locator": "replacement.cpp L294-295, L439-440"} {"id": "ext.draw_screen_background entry.Sgd2fr_D2Client_DrawScreenBackground", "kind": "function", "status": "sourced", "trust": "trusted", "module": "draw_screen_background entry", "author": "Mir Drualga (SGD2FreeRes)", "desc": "Public interception entry (extern \"C\" __cdecl). Reads d2client::GetScreenOpenMode() and dispatches: kRight -> DrawRight{Background,BorderFrame,BackgroundRibbon}; kLeft -> DrawLeft*; kBoth -> both; kNone -> nothing. Then calls original d2::d2client::DrawScreens(). Declared in replacement.hpp. | src: extern \"C\" void __cdecl Sgd2fr_D2Client_DrawScreenBackground();", "source": ["https://github.com/mir-diablo-ii-tools/SlashGaming-Diablo-II-Free-Resolution"], "locator": "replacement.cpp L959-1007"} {"id": "ext.patch_1_09dcpp GetPatchAddressAndSize01.DrawScreenBackground_CALL_hook_1_13c", "kind": "function", "status": "sourced", "trust": "trusted", "module": "patch_1_09d.cpp GetPatchAddressAndSize01", "author": "Mir Drualga (SGD2FreeRes)", "desc": "1.13c call-branch patch that redirects into Sgd2fr_D2Client_DrawScreenBackground via the asm shim InterceptionFunc01. Found by tracing the 'ACT%d' string usage to the function return. Other versions: 1.09D 0x8696B, 1.10 0x81F08, 1.12A 0x90216, 1.13D 0x1D4A6, LoD1.14C 0x5264D, LoD1.14D 0x56FAF (all size 5).", "source": ["https://github.com/mir-diablo-ii-tools/SlashGaming-Diablo-II-Free-Resolution"], "rva": "0xc3aa6", "value": "0xC3AA6 (0xC3AAB-0xC3AA6 = 5 bytes)"} {"id": "ext.patch_1_09dcpp GetPatchAddressAndSize02.Disable_stock_LEFT_screen_bg_1_13c", "kind": "function", "status": "sourced", "trust": "trusted", "module": "patch_1_09d.cpp GetPatchAddressAndSize02", "author": "Mir Drualga (SGD2FreeRes)", "desc": "NOP patch removing the game's original left-screen 800BorderFrame draw. Located via the 'Panel\\800BorderFrame' string (two usages; this is the left one). 1.09D 0x58F1B(sz0x96), 1.10 0x5F4EB(0x9B), 1.12A 0x8218D(0x9A), 1.13D 0x6D2DD(0x9A), LoD1.14C 0x94B0C(0xAA), LoD1.14D 0x9865E(0x9E).", "source": ["https://github.com/mir-diablo-ii-tools/SlashGaming-Diablo-II-Free-Resolution"], "rva": "0x271ed", "value": "0x271ED (0x27287-0x271ED = 0x9A bytes NOP)"} {"id": "ext.patch_1_09dcpp GetPatchAddressAndSize03.Disable_stock_RIGHT_screen_bg_1_13c", "kind": "function", "status": "sourced", "trust": "trusted", "module": "patch_1_09d.cpp GetPatchAddressAndSize03", "author": "Mir Drualga (SGD2FreeRes)", "desc": "NOP patch removing the game's original right-screen 800BorderFrame draw. 1.09D 0x58FF0(0xAC), 1.10 0x5F5C0(0xAC), 1.12A 0x82094(0xB9), 1.13D 0x6D1E1(0xBD), LoD1.14C 0x94BF1(0xB3), LoD1.14D 0x98733(0xA7).", "source": ["https://github.com/mir-diablo-ii-tools/SlashGaming-Diablo-II-Free-Resolution"], "rva": "0x270f1", "value": "0x270F1 (0x271AE-0x270F1 = 0xBD bytes NOP)"} {"id": "ext.set_screen_shift.Sgd2fr_D2Client_SetScreenShift", "kind": "function", "status": "sourced", "trust": "trusted", "module": "set_screen_shift", "author": "Mir Drualga (SGD2FreeRes)", "desc": "THE origin of the -320 render shift. Recomputes D2's screen-shift so the 640x480 play area is centered. screen_shift_x = (general_display_width/2) - (640/2); screen_shift_y = -((general_display_height/2) - (480/2)). Note the 640/2 = 320 term and the NEGATION on the Y term. For a 1280x720 display: shift_x = 640-320 = 320, shift_y = -(360-240) = -120. The '-320'-family value is the (640/2) offset that recenters the viewport origin. Uses d2client::GetGeneralDisplayWidth/Height a | src: int screen_shift_x = (general_display_width / 2) - (640 / 2); int screen_shift_y = -((general_display_height / 2) - (480 / 2)); ::d2::d2client::SetScreenShiftX(screen_shift_x); ", "source": ["https://github.com/mir-diablo-ii-tools/SlashGaming-Diablo-II-Free-Resolution"], "locator": "set_screen_shift/replacement.cpp L54-63"} {"id": "ext.set_screen_shift/patch_1_09dcpp.SetScreenShift_CALL_hook_1_13c", "kind": "function", "status": "sourced", "trust": "trusted", "module": "set_screen_shift/patch_1_09d.cpp", "author": "Mir Drualga (SGD2FreeRes)", "desc": "Call-branch patch feeding Sgd2fr_D2Client_SetScreenShift. Found via write-breakpoint on ScreenShiftX/Y variable. 1.09D 0x865BF, 1.10 0x81B8F, 1.12A 0x90166, 1.13D 0x1D3F6, LoD1.14C 0x5259B, LoD1.14D 0x56EFD (all size 0x27 = 0x...1D-0x...F6).", "source": ["https://github.com/mir-diablo-ii-tools/SlashGaming-Diablo-II-Free-Resolution"], "rva": "0xc39f6", "value": "0xC39F6 (0xC3A1D-0xC39F6 = 0x27 bytes)"} {"id": "struct.CullingSpec", "kind": "struct", "status": "sourced", "trust": "trusted", "module": "set_tile_culling_bound", "author": "Mir Drualga (SGD2FreeRes)", "desc": "Struct the game passes to the tile-culling function. Layout verified by static_assert: flags at 0x0 (uint32_t), draw_window_rect (RECT) at 0x4, tile_culling_window (RECT) at 0x14 (20). RECT is 16 bytes (left/top/right/bottom int32). | src: struct CullingSpec { uint32_t flags; RECT draw_window_rect; RECT tile_culling_window; }; static_assert(offsetof(CullingSpec, flags)==0); static_assert(offsetof(CullingSpec, draw_wi", "source": ["https://github.com/mir-diablo-ii-tools/SlashGaming-Diablo-II-Free-Resolution"], "locator": "set_tile_culling_bound/replacement.cpp L292-300"} {"id": "ext.set_tile_culling_bound.Sgd2fr_D2Client_SetTileCullingBound", "kind": "function", "status": "sourced", "trust": "trusted", "module": "set_tile_culling_bound", "author": "Mir Drualga (SGD2FreeRes)", "desc": "Sets the map/tile draw and culling windows. draw_window_rect = SetRect(left,top,right,bottom) from args. tile_culling_window base = SetRect(-80, -80, width+80, height+40) using GetGeneralDisplayWidth/Height. If perspective mode enabled, expands top/left/right/bottom by ratios (866px up = -204.375 unit space; ratio = 1732/(1732-height/2) - 1, capped at 1.0; bottom uses ratio = 1 - 1500/(1500+height/2)). Finally sets culling_spec->flags |= 0x1. The -80/-80/+80/+40 margins are t | src: SetRect(tile_culling_rect, -80, -80, width + 80, height + 40); ... culling_spec->flags |= 0x1;", "source": ["https://github.com/mir-diablo-ii-tools/SlashGaming-Diablo-II-Free-Resolution"], "locator": "set_tile_culling_bound/replacement.cpp L302-363"} {"id": "ext.set_tile_culling_bound/patch_1_11cpp.SetTileCullingBound_JMP_hook_1_13c", "kind": "function", "status": "sourced", "trust": "trusted", "module": "set_tile_culling_bound/patch_1_11.cpp", "author": "Mir Drualga (SGD2FreeRes)", "desc": "Jump-branch patch to the tile-culling replacement (via patch_1_11_shim). Found via 'Perspective' Video-Options string -> first D2Client-space call. 1.11 0x5B560, 1.11B 0x927A0, 1.12A 0xBA990, 1.13ABeta 0x3F490, 1.13D 0xB5330, LoD1.14A 0xB5330 (all size 5). Separate patch_1_07.cpp covers 1.07-1.10 & 1.14A-D with different offsets (e.g. 1.09D 0x16000, LoD1.14C 0x71D30, LoD1.14D 0x76000).", "source": ["https://github.com/mir-diablo-ii-tools/SlashGaming-Diablo-II-Free-Resolution"], "rva": "0x8a4d0", "value": "0x8A4D0 (size 5, JMP)"} {"id": "ext.set_cel_display_left_and_right.Sgd2fr_D2GDI_SetCelDisplayLeftAndRight", "kind": "function", "status": "sourced", "trust": "trusted", "module": "set_cel_display_left_and_right", "author": "Mir Drualga (SGD2FreeRes)", "desc": "Sets the D2GDI cel horizontal draw window to the full width: SetCelDisplayLeft(0), SetCelDisplayRight(resolution.width). Resolution from GetIngameResolutionFromId(resolution_mode). This is the render-window widening that removes the stock 640-wide clip so the perimeter can be drawn. | src: d2::d2gdi::SetCelDisplayLeft(0); d2::d2gdi::SetCelDisplayRight(resolution.width);", "source": ["https://github.com/mir-diablo-ii-tools/SlashGaming-Diablo-II-Free-Resolution"], "locator": "d2gdi/set_cel_display_left_and_right/replacement.cpp L208-213"} {"id": "ext.d2gdi set_cel_display_left_and_right/patch_1_13ccpp.SetCelDisplayLeftAndRight_JMP_hook_1_13c", "kind": "function", "status": "sourced", "trust": "trusted", "module": "d2gdi set_cel_display_left_and_right/patch_1_13c.cpp", "author": "Mir Drualga (SGD2FreeRes)", "desc": "Jump-branch patch in D2GDI (not D2Client) for the cel display left/right. 1.11 0x6529, 1.11B 0x7239, 1.12A 0x6599, 1.13ABeta 0x65F9, 1.13C 0x7049, 1.13D 0x7E99 (size 0x2E each). Library = kD2GDI.", "source": ["https://github.com/mir-diablo-ii-tools/SlashGaming-Diablo-II-Free-Resolution"], "rva": "0x7049", "value": "0x7049 (0x7077-0x7049 = 0x2E)"} {"id": "ext.set_general_display_width_and_height.Sgd2fr_D2Client_SetGeneralDisplayWidthAndHeigh", "kind": "function", "status": "sourced", "trust": "trusted", "module": "set_general_display_width_and_height", "author": "Mir Drualga (SGD2FreeRes)", "desc": "Feeds the resolution into the GeneralDisplayWidth/Height globals that everything above reads: SetGeneralDisplayWidth(resolution.width), SetGeneralDisplayHeight(resolution.height). Also cycles SetInventoryArrangeMode(inventory_arrange_mode++) as a workaround to stop inventory arrangement from transferring (overflow intentional). | src: d2::d2client::SetGeneralDisplayWidth(resolution.width); d2::d2client::SetGeneralDisplayHeight(resolution.height);", "source": ["https://github.com/mir-diablo-ii-tools/SlashGaming-Diablo-II-Free-Resolution"], "locator": "set_general_display_width_and_height/replacement.cpp L414-427"} {"id": "ext.position_realignment.RealignPositionFromCenter", "kind": "function", "status": "sourced", "trust": "trusted", "module": "position_realignment", "author": "Mir Drualga (SGD2FreeRes)", "desc": "Re-anchors a PositionalRectangle from the source (inventory-arrange) resolution center to the current resolution center, preserving width/height. dist = out.Left - source.width/2; out.Left = current.width/2 + dist; out.Right = out.Left + rectangle_width. Same for top/bottom about height/2. Uses GetIngameResolutionFromId(GetResolutionMode()) and GetSourceInventoryArrangeResolution(). | src: out_position_wrapper.SetLeft((current_resolution.width / 2) + dist_from_rect_left_to_display_center);", "source": ["https://github.com/mir-diablo-ii-tools/SlashGaming-Diablo-II-Free-Resolution"], "locator": "helper/position_realignment.cc L118-150"} {"id": "ext.position_realignment.RealignPositionFromBottomCenter", "kind": "function", "status": "sourced", "trust": "trusted", "module": "position_realignment", "author": "Mir Drualga (SGD2FreeRes)", "desc": "Like RealignPositionFromCenter for X, but anchors Y to the display BOTTOM: dist_from_rect_top_to_display_bottom = source.height - out.Top; out.Top = current.height - dist; out.Bottom = out.Top + rectangle_height. Used for bottom-docked UI (belt/skill bar).", "source": ["https://github.com/mir-diablo-ii-tools/SlashGaming-Diablo-II-Free-Resolution"], "locator": "helper/position_realignment.cc L152-184"} {"id": "ext.DisableScrollOfInifussRectPatch_1_07_NOP", "kind": "function", "status": "sourced", "trust": "trusted", "module": "", "author": "Mir Drualga (SGD2FreeRes)", "desc": "NOPs the D2GFX.DrawRectangle call that draws the black rectangle on the Scroll-of-Inifuss (Cain quest) screen, which otherwise mis-renders at high res. Located via the '%s\\UI\\MENU\\scroin' string then scrolling up to the DrawRectangle call. Single NOP patch per version. 1.13C at D2Client +0x7C38D (size 0x2D = 0x7C3BA-0x7C38D); 1.09D 0x8330C, 1.12A 0x70FBD, 1.13D 0x7516D, LoD1.14C 0x9C20D, LoD1.14D 0x9FA20 (all size 0x2D). Applies to essentially all versions 1.07-1.14D.", "source": ["https://github.com/mir-diablo-ii-tools/SlashGaming-Diablo-II-Free-Resolution"], "locator": "disable_scroll_of_inifuss_rect/patch_1_07.cpp", "value": "1.13C: 0x7C38D (0x2D NOP)"} {"id": "ext.draw_screen_background.draw_screen_background_border_ribbon_fns", "kind": "note", "status": "sourced", "trust": "trusted", "module": "draw_screen_background", "author": "Mir Drualga (SGD2FreeRes)", "desc": "DrawLeftScreenBackgroundRibbon / DrawRightScreenBackgroundRibbon tile horizontal and vertical 'ribbon' DC6s across the perimeter beyond the border frame, using inner-panel reference height (256+176)=432 for vertical centering; border_left = screen_left - firstFrameWidth; loops fill until width_covered/height_covered exceed borders. Config-gated by IsScreenBorderFrameEnabled(); original-vs-custom chosen by IsUseOriginalScreenBorderFrame().", "source": ["https://github.com/mir-diablo-ii-tools/SlashGaming-Diablo-II-Free-Resolution"], "locator": "replacement.cpp L592-955"} {"id": "ext.d2dx.RenderContext_UpdateViewport", "kind": "function", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog (D2DX)", "desc": "Sets viewport + scissor from a Rect, then updates the Constants CB. Verbatim: CD3D11_VIEWPORT viewport{ (float)rect.offset.x, (float)rect.offset.y, (float)rect.size.width, (float)rect.size.height }; _deviceContext->RSSetViewports(1,&viewport); CD3D11_RECT scissorRect{ rect.offset.x, rect.offset.y, rect.size.width, rect.size.height }; _deviceContext->RSSetScissorRects(1,&scissorRect); then writes _constants.screenSize[0/1]=size.width/height, invScreenSize=1/size, flags[0]=NoAn | src: CD3D11_VIEWPORT viewport{ (float)rect.offset.x, (float)rect.offset.y, (float)rect.size.width, (float)rect.size.height };", "source": ["https://github.com/bolrog/d2dx"], "locator": "RenderContext.cpp UpdateViewport(Rect rect)"} {"id": "ext.d2dx.Scissor_rect_construction_quirk_right_bottom_s", "kind": "note", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog (D2DX)", "desc": "CD3D11_RECT ctor is (left,top,right,bottom) but D2DX passes { offset.x, offset.y, size.width, size.height } -> right=size.width, bottom=size.height rather than offset.x+width / offset.y+height. Harmless when offset==0 (offscreen render at {0,0,gameSize}) but with a centered _renderRect (non-zero offset in Present) the scissor's right/bottom fall short by offset.x/offset.y. Viewport still places content correctly; only the scissor is mismatched. Load-bearing if chasing edge-cl | src: CD3D11_RECT scissorRect{ rect.offset.x, rect.offset.y, rect.size.width, rect.size.height };", "source": ["https://github.com/bolrog/d2dx"], "locator": "RenderContext.cpp UpdateViewport scissorRect"} {"id": "ext.d2dx.UpdateViewport_call_sites", "kind": "function", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog (D2DX)", "desc": "Called 3 places. SetSizes: UpdateViewport({0,0,_gameSize.width,_gameSize.height}) (offscreen game-size target, offset 0). Present: called with game-size dims AND with _renderRect (the centered/scaled final blit to screen). WriteToScreen: UpdateViewport({0,0,_gameSize.width,_gameSize.height}). Only the Present-with-_renderRect path carries a non-zero centering offset.", "source": ["https://github.com/bolrog/d2dx"], "locator": "RenderContext.cpp SetSizes / Present / WriteToScreen"} {"id": "ext.d2dx.RenderContext_SetSizes", "kind": "function", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog (D2DX)", "desc": "Stores _gameSize/_windowSize. displaySize = (FullscreenDefault ? _desktopSize : _windowSize). _renderRect = Metrics::GetRenderRect(_gameSize, displaySize, !NoWide flag). Computes desktopCenterX=_desktopSize.width/2, desktopCenterY=(FullscreenDefault?_desktopSize.height/2:_desktopClientMaxHeight/2), reads GetWindowPosition() preferred position (used iff x>=0 && y>=0). Branches Windowed vs FullscreenDefault for placement. Then ClipCursor(); and if(_resources){ ResizeBackbuffer( | src: _renderRect = Metrics::GetRenderRect(_gameSize, displaySize, !_d2dxContext->GetOptions().GetFlag(OptionsFlag::NoWide));", "source": ["https://github.com/bolrog/d2dx"], "locator": "RenderContext.cpp SetSizes(Size gameSize, Size windowSize)"} {"id": "ext.d2dx.RenderContext_Draw", "kind": "function", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog (D2DX)", "desc": "SetBlendState(batch.GetAlphaBlend()); picks atlas via GetTextureCache(batch); SetShaderState with Game vertex+pixel shaders, atlas SRV (batch.GetTextureAtlas()) and Palette Texture1D SRV; then _deviceContext->Draw(batch.GetVertexCount(), startVertexLocation + batch.GetStartVertex()). No positional transform here — geometry comes straight from the vertex buffer; the only offset is the vertex START index. | src: _deviceContext->Draw(batch.GetVertexCount(), startVertexLocation + batch.GetStartVertex());", "source": ["https://github.com/bolrog/d2dx"], "locator": "RenderContext.cpp Draw(const Batch& batch, uint32_t startVertexLocation)"} {"id": "struct.Constants_shader_constant_buffer", "kind": "struct", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog (D2DX)", "desc": "Full layout (32 bytes, static_assert): float screenSize[2]={0,0}; float invScreenSize[2]={0,0}; uint32_t flags[4]={0,0,0,0};. NO translate/offset/textureOffset field exists. Therefore the GPU-side constants apply NO per-batch or per-geometry positional translate; any floor-vs-wall positional difference must originate in the CPU vertex data, not the CB. | src: float screenSize[2]; float invScreenSize[2]; uint32_t flags[4]; // static_assert size==32", "source": ["https://github.com/bolrog/d2dx"], "locator": "RenderContext.h Constants"} {"id": "struct.MetricsTableEntry_baked_gameSize_table", "kind": "struct", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog (D2DX)", "desc": "struct with 3 Size fields: desktopSize, gameSize, gameSizeWide. 26 rows (desktop -> game / gameWide): 1280x720->960x720/1280x720; 1360x768->1024x768/1360x768; 1366x768->1024x768/1366x768; 1280x800->1066x800/1280x800; 1536x864->1152x864/1536x864; 1440x900->1200x900/1440x900; 1600x900->1200x900/1600x900; 1280x1024->640x480/640x512; 1400x1050->700x525/700x525; 1680x1050->700x525/840x525; 1920x1080->720x540/960x540; 2560x1080->720x540/960x540; 2048x1152->768x576/1024x576; 1600x12", "source": ["https://github.com/bolrog/d2dx"], "locator": "Metrics.cpp MetricsTable[26]", "value": "26 entries; desktopSize/gameSize/gameSizeWide"} {"id": "ext.d2dx.Metrics_GetSuggestedGameSize", "kind": "function", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog (D2DX)", "desc": "First tries MetricsTable exact-match on desktop size (narrow vs wide variant). Fallback: loop scaleFactor=1..8 { size.width=desktop.width/scaleFactor; size.height=desktop.height/scaleFactor; if (desktop.height/(scaleFactor+1) <= 600) break; }. Height cap: if size.height>720 { aspect=desktop.width/desktop.height; size.width=(int32_t)(aspect*720); size.height=720; }. Constants: 600 (break threshold), 720 (max game height), scale range 1..8.", "source": ["https://github.com/bolrog/d2dx"], "locator": "Metrics.cpp GetSuggestedGameSize", "value": "600 break, 720 cap, scale 1..8"} {"id": "ext.d2dx.Metrics_GetRenderRect", "kind": "function", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog (D2DX)", "desc": "Integer scale: scaleFactor=1; while(gameSize.width*(scaleFactor+1)<=desktop.width && gameSize.height*(scaleFactor+1)<=desktop.height) ++scaleFactor;. Centering (integer): rect.size={gameSize.width*scaleFactor, gameSize.height*scaleFactor}; rect.offset.x=(desktop.width-gameSize.width*scaleFactor)/2; rect.offset.y=(desktop.height-gameSize.height*scaleFactor)/2. Non-integer trigger: if(rect.offset.x<0 || rect.offset.y<0 || (rect.offset.x>=16 && rect.offset.y>=16)) apply fraction", "source": ["https://github.com/bolrog/d2dx"], "locator": "Metrics.cpp GetRenderRect(gameSize, desktopSize, wide)", "value": "16px margin threshold; integer-then-fractional centering"} {"id": "ext.d2dx.SurfaceIdTracker_UpdateBatchSurfaceId_retag_ru", "kind": "function", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog (D2DX)", "desc": "Assigns/reuses a surfaceId per batch (tag stored on vertices via SetSurfaceId; used by AA/edge pixel shader, NOT a positional transform). Order: (1) if majorGameState!=InGame -> D2DX_SURFACE_ID_USER_INTERFACE. (2) if chroma-key disabled (text bg) -> UI. (3) gameplay-with-chroma UI reclassifications: draw-line single-pixel '(maxy - miny) == 1' -> UI; bottom band 'miny >= (gameSize.height - 48)' -> UI (48px); panels: '(_gameHelper->ScreenOpenMode() & 1)' left-panel open && 'min", "source": ["https://github.com/bolrog/d2dx"], "locator": "SurfaceIdTracker.cpp UpdateBatchSurfaceId", "value": "48px bottom band; 32x32 tile adjacency; ScreenOpenMode &1/&2"} {"id": "ext.d2dx.OnBufferSwap_UnitMotionPrediction_per_vertex_t", "kind": "function", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog (D2DX)", "desc": "KEY per-batch positional translate. Gated by IsFeatureEnabled(Feature::UnitMotionPrediction) && _majorGameState==MajorGameState::InGame. offset = _unitMotionPredictor.GetOffset(_gameHelper->GetPlayerUnit()). Applied to EVERY batch EXCEPT surfaceId==D2DX_SURFACE_ID_USER_INTERFACE and TextureCategory::Player, via _vertices.items[vertexIndex++].AddOffset(-offset.x, -offset.y) (NEGATED). Floor AND wall batches are non-UI/non-player, so BOTH receive -offset; player+UI stay put. No | src: _vertices.items[vertexIndex++].AddOffset(-offset.x, -offset.y);", "source": ["https://github.com/bolrog/d2dx"], "locator": "D2DXContext.cpp OnBufferSwap ~lines 380-410"} {"id": "ext.d2dx.OnDrawLine_weather_particle_motion_offset", "kind": "function", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog (D2DX)", "desc": "Weather/rain particle motion prediction: computes a directional offset and applies startPos += offset; endPos += offset; to line endpoints before vertex creation (~640-644). Separate from the world-geometry offset; affects only line primitives (weather).", "source": ["https://github.com/bolrog/d2dx"], "locator": "D2DXContext.cpp OnDrawLine ~605-650"} {"id": "ext.d2dx.Mouse_position_scale_center_mapping", "kind": "function", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog (D2DX)", "desc": "pos.x=(int32_t)(pos.x*scale+mouseOffsetX); pos.y=(int32_t)(pos.y*scale); maps OS cursor into scaled/centered render area (mouseOffsetX centers horizontally in fullscreen). Confirms centering offset is horizontal-only for cursor; not applied to world geometry.", "source": ["https://github.com/bolrog/d2dx"], "locator": "D2DXContext.cpp OnMouseMoveMessage/OnSetCursorPos ~948-977"} {"id": "ext.d2dx.NO_per_batch_floor_vs_wall_transform_exists", "kind": "note", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog / Necrolis (D2DX)", "desc": "Grep + full read of D2DXContext.cpp, RenderContext.cpp, GameHelper.cpp: TextureCategory::Floor(4) and Wall(6) are never used to apply any positional offset/transform/scissor/viewport difference. They drive only texture categorization/cache selection and motion-prediction exclusion. Floor and wall are treated identically for geometry.", "source": ["https://github.com/Necrolis/d2dx-annihilus"], "locator": "whole codebase", "value": "none"} {"id": "ext.glide3xcpp.grDrawVertexArray_capture_seam", "kind": "function", "status": "sourced", "trust": "trusted", "module": "glide3x.cpp", "author": "bolrog / Necrolis (D2DX)", "desc": "Primary draw capture. Grabs _ReturnAddress() and forwards to the context factory singleton. This return address is later used to classify the draw as floor/wall/etc. | src: const auto returnAddress = (uintptr_t)_ReturnAddress(); D2DXContextFactory::GetInstance()->OnDrawVertexArray(mode, Count, (uint8_t**)pointers, returnAddress);", "source": ["https://github.com/Necrolis/d2dx-annihilus"], "locator": "glide3x.cpp grDrawVertexArray"} {"id": "ext.glide3xcpp.grDrawVertexArrayContiguous_capture_seam", "kind": "function", "status": "sourced", "trust": "trusted", "module": "glide3x.cpp", "author": "bolrog / Necrolis (D2DX)", "desc": "Second capture path (used for 4-vertex TRIANGLE_FAN quads). Same _ReturnAddress() -> OnDrawVertexArrayContiguous(mode,Count,vertex,stride,returnAddress). | src: D2DXContextFactory::GetInstance()->OnDrawVertexArrayContiguous(mode, Count, (uint8_t*)vertex, stride, returnAddress);", "source": ["https://github.com/Necrolis/d2dx-annihilus"], "locator": "glide3x.cpp grDrawVertexArrayContiguous"} {"id": "ext.glide3xcpp.grViewport_is_a_no_op_asserts_origin_0_0", "kind": "function", "status": "sourced", "trust": "trusted", "module": "glide3x.cpp", "author": "bolrog / Necrolis (D2DX)", "desc": "Glide grViewport does nothing except assert x==0 && y==0. The game never sets a shifted Glide viewport; all viewport control is D2DX-internal. | src: grViewport(FxI32 x, FxI32 y, FxI32 width, FxI32 height){ assert(x == 0 && y == 0); }", "source": ["https://github.com/Necrolis/d2dx-annihilus"], "locator": "glide3x.cpp grViewport"} {"id": "ext.glide3xcpp.grClipWindow_unsupported_grCoordinateSpace_emp", "kind": "function", "status": "sourced", "trust": "trusted", "module": "glide3x.cpp", "author": "bolrog / Necrolis (D2DX)", "desc": "grClipWindow => assert(false, Unsupported). grCoordinateSpace is an empty stub. No Glide-level scissor/clip or coordinate-space transform enters the pipeline. | src: grClipWindow(...){ assert(false && \"grClipWindow: Unsupported\"); } grCoordinateSpace(GrCoordinateSpaceMode_t mode){ }", "source": ["https://github.com/Necrolis/d2dx-annihilus"], "locator": "glide3x.cpp grClipWindow / grCoordinateSpace"} {"id": "ext.glide3xcpp.grSstWinOpen_OnSstWinOpen", "kind": "function", "status": "sourced", "trust": "trusted", "module": "glide3x.cpp", "author": "bolrog / Necrolis (D2DX)", "desc": "Resolves 640x480/800x600/1024x768 then calls OnSstWinOpen(hWnd,width,height). Asserts color_format==GR_COLORFORMAT_RGBA. | src: D2DXContextFactory::GetInstance()->OnSstWinOpen(hWnd, width, height); return 1;", "source": ["https://github.com/Necrolis/d2dx-annihilus"], "locator": "glide3x.cpp grSstWinOpen"} {"id": "ext.d2dx.D2DXContext_PrepareBatchForSubmit", "kind": "function", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog / Necrolis (D2DX)", "desc": "Where a Batch's category is finalized. gameAddress = IdentifyGameAddress(returnAddress); category = RefineTextureCategoryFromGameAddress(existing, gameAddress). Sets StartVertex=_vertexCount, VertexCount. NO position offset applied for any category. | src: batch.SetTextureCategory(_gameHelper->RefineTextureCategoryFromGameAddress(batch.GetTextureCategory(), gameAddress));", "source": ["https://github.com/Necrolis/d2dx-annihilus"], "locator": "D2DXContext.cpp:754-778"} {"id": "ext.d2dx.D2DXContext_OnBufferSwap_unit_MoP_offset_loop", "kind": "function", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog / Necrolis (D2DX)", "desc": "THE ONLY post-capture positional shift of world geometry. If UnitMotionPrediction enabled and InGame: offset=_unitMotionPredictor.GetOffset(playerUnit); then for every batch with surfaceId != D2DX_SURFACE_ID_USER_INTERFACE AND category != Player, each vertex gets AddOffset(-offset.x,-offset.y). Floor AND wall both qualify -> identical uniform shift. | src: if (surfaceId != D2DX_SURFACE_ID_USER_INTERFACE && batch.GetTextureCategory() != TextureCategory::Player){ ... _vertices.items[vertexIndex++].AddOffset(-offset.x, -offset.y); }", "source": ["https://github.com/Necrolis/d2dx-annihilus"], "locator": "D2DXContext.cpp:408-436"} {"id": "ext.d2dx.D2DXContext_DrawBatches_merge", "kind": "function", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog / Necrolis (D2DX)", "desc": "After BulkWriteVertices, merges consecutive batches when same texture-cache/atlas/alphaBlend and combined vertexCount<=65535, else flushes via _renderContext->Draw(mergedBatch,startVertexLocation). Category is NOT part of the merge key and NOT used to offset. | src: _renderContext->GetTextureCache(batch) != _renderContext->GetTextureCache(mergedBatch) || batch.GetTextureAtlas() != mergedBatch.GetTextureAtlas() || batch.GetAlphaBlend() != merge", "source": ["https://github.com/Necrolis/d2dx-annihilus"], "locator": "D2DXContext.cpp:354-405"} {"id": "ext.d2dx.RenderContext_UpdateViewport_single_uniform_vi", "kind": "function", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog / Necrolis (D2DX)", "desc": "Sets ONE viewport and ONE scissor rect, both == the passed Rect (offset+size). Also writes Constants.screenSize/invScreenSize used by the vertex shader to map int16 screen coords to NDC. No per-batch or per-category viewport/scissor; set per render-pass only. | src: CD3D11_VIEWPORT viewport{ (float)rect.offset.x, (float)rect.offset.y, (float)rect.size.width, (float)rect.size.height }; ... CD3D11_RECT scissorRect{ rect.offset.x, rect.offset.y, ", "source": ["https://github.com/Necrolis/d2dx-annihilus"], "locator": "RenderContext.cpp:633-657"} {"id": "ext.d2dx.RenderContext_Present_viewport_sequence", "kind": "function", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog / Necrolis (D2DX)", "desc": "Game batches render into the Game framebuffer under UpdateViewport({0,0,_gameSize.width,_gameSize.height}) (set at end of prior Present, line 491). Gamma/AA passes also use {0,0,gameSize}. Final display blit to backbuffer uses UpdateViewport(_renderRect) (centered, letterboxed dest). gameSize=internal render res; renderRect=on-screen placement. | src: UpdateViewport({ 0,0,_gameSize.width, _gameSize.height }); ... UpdateViewport(_renderRect);", "source": ["https://github.com/Necrolis/d2dx-annihilus"], "locator": "RenderContext.cpp:336-502"} {"id": "ext.d2dx.RenderContext_Draw_per_batch_no_transform", "kind": "function", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog / Necrolis (D2DX)", "desc": "Per merged batch: SetBlendState, pick atlas SRV, SetShaderState(Game VS/PS), then Draw(vertexCount, startVertexLocation + batch.GetStartVertex()). No matrix/offset/scissor per batch or category. | src: _deviceContext->Draw(batch.GetVertexCount(), startVertexLocation + batch.GetStartVertex());", "source": ["https://github.com/Necrolis/d2dx-annihilus"], "locator": "RenderContext.cpp:310-326"} {"id": "ext.d2dx.UnitMotionPredictor_UnitMotion_GetOffset_iso_p", "kind": "function", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog / Necrolis (D2DX)", "desc": "Converts predicted vs last world pos (16.16 fixed) into a SCREEN-space isometric pixel offset. scaleFactors={32/sqrt2,16/sqrt2}; screenOffset=scaleFactors*{dx-dy,dx+dy}+0.5. Magnitude of the uniform world shift; a few px, never hundreds. | src: const OffsetF scaleFactors{ 32.0f / sqrtf(2.0f), 16.0f / sqrtf(2.0f) }; const OffsetF screenOffset = scaleFactors * OffsetF{ offset.x - offset.y, offset.x + offset.y } + 0.5f;", "source": ["https://github.com/Necrolis/d2dx-annihilus"], "locator": "UnitMotionPredictor.cpp:247-253"} {"id": "ext.d2dx.GameHelper_RefineTextureCategoryFromGameAddres", "kind": "function", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog / Necrolis (D2DX)", "desc": "Maps captured return address's GameAddress to a category ONLY when previous category is Unknown: DrawFloor->Floor, DrawWall1/DrawWall2->Wall, else unchanged. Category never triggers coordinate change. | src: case GameAddress::DrawFloor: return TextureCategory::Floor; case GameAddress::DrawWall1: case GameAddress::DrawWall2: return TextureCategory::Wall;", "source": ["https://github.com/Necrolis/d2dx-annihilus"], "locator": "GameHelper.cpp:359-381"} {"id": "ext.d2dx.gameAddresses_tables_DrawFloor_DrawWall_return", "kind": "global", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog / Necrolis (D2DX)", "desc": "Per-version glide3x.dll return-address constants identifying floor/wall draws. Index order: [1]=DrawWall1,[2]=DrawWall2,[3]=DrawFloor. | src: 113c: 0x6f8567ab DrawWall1, 0x6f8567b9 DrawWall2, 0x6f85befc DrawFloor | 114d: 0x50d39f DrawWall1, 0x50d3ae DrawWall2, 0x50db03 DrawFloor | 109d: 0x6f818468/0x6f818476/0x6f813e2f", "source": ["https://github.com/Necrolis/d2dx-annihilus"], "locator": "GameHelper.cpp:120-190"} {"id": "struct.Batch_16_bytes", "kind": "struct", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog / Necrolis (D2DX)", "desc": "Packed 16-byte batch key. uint32 _textureHash @0; uint16 _startVertexLow @4; uint16 _vertexCount @6; uint16 _textureStartAddress @8 (byte addr/256 stored as (addr>>8)+1); uint16 _startVertexHigh_textureIndex @10 (VVVV + 12-bit texIndex); uint8 _textureHeight_textureWidth_alphaBlend @12 (HHHWWWBB); uint8 _isChromaKeyEnabled_gameAddress_paletteIndex @13 (CGGGPPPP); uint8 _textureCategory_primitiveType_combiners @14 (category in bits 5-7); uint8 _textureAtlas @15 (bits 0-2). No | src: uint8_t _textureCategory_primitiveType_combiners; // TTT.PPCC (GetTextureCategory = value>>5)", "source": ["https://github.com/Necrolis/d2dx-annihilus"], "locator": "Batch.h:242-254"} {"id": "struct.Vertex_16_bytes_int16_screen_coords", "kind": "struct", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog / Necrolis (D2DX)", "desc": "int16 _x,_y,_s,_t; uint32 _color; uint16 _paletteIndex_atlasIndex (palette<<12 | atlas&4095); uint16 _isChromaKeyEnabled_surfaceId (bit14 chroma | surfaceId&16383). Position is int16 screen-space; ctor asserts x,y in [INT16_MIN,INT16_MAX]. AddOffset(x,y) does _x+=x,_y+=y — mechanism the MoP loop uses. | src: int16_t _x; int16_t _y; int16_t _s; int16_t _t; ... inline void AddOffset(int32_t x,int32_t y){ _x += x; _y += y; }", "source": ["https://github.com/Necrolis/d2dx-annihilus"], "locator": "Vertex.h:133-143"} {"id": "struct.TextureCategory_enum", "kind": "struct", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog / Necrolis (D2DX)", "desc": "Unknown=0, MousePointer=1, Player=2, LoadingScreen=3, Floor=4, TitleScreen=5, Wall=6, UserInterface=7, Count=8. Floor and Wall distinct values but geometry-identical. | src: Floor = 4, TitleScreen = 5, Wall = 6, UserInterface = 7", "source": ["https://github.com/Necrolis/d2dx-annihilus"], "locator": "Types.h:84-95"} {"id": "struct.GameAddress_enum", "kind": "struct", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog / Necrolis (D2DX)", "desc": "Unknown=0, DrawWall1=1, DrawWall2=2, DrawFloor=3, DrawShadow=4, DrawDynamic=5, DrawSomething1=6, DrawLine=7, Count=8. Index into gameAddresses_* tables. | src: DrawWall1 = 1, DrawWall2 = 2, DrawFloor = 3, DrawShadow = 4, DrawDynamic = 5", "source": ["https://github.com/Necrolis/d2dx-annihilus"], "locator": "Types.h:108-119"} {"id": "ext.d2dx.D2DX_SURFACE_ID_USER_INTERFACE", "kind": "global", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog / Necrolis (D2DX)", "desc": "=16383. UI surfaceId; MoP loop skips batches whose start vertex has this surfaceId (UI never shifts, world geometry incl. floor/wall does).", "source": ["https://github.com/Necrolis/d2dx-annihilus"], "locator": "Types.h:32", "value": "16383"} {"id": "ext.d2dx.OnSstWinOpen_gameSize_windowSize_logic", "kind": "function", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog / Necrolis (D2DX)", "desc": "Computes gameSize from width/height (or _customGameSize override); if NoResMod off, windowSize forced 800x600; if gameSize != 640x480 then windowSize=gameSize. Creates/resizes RenderContext with (gameSize, windowSize*windowScale). Establishes internal render res (gameSize) that becomes the {0,0,gameSize} viewport. | src: Size gameSize{ width, height }; if (_customGameSize.width > 0){ gameSize = _customGameSize; } if (gameSize.width != 640 || gameSize.height != 480){ windowSize = gameSize; }", "source": ["https://github.com/Necrolis/d2dx-annihilus"], "locator": "D2DXContext.cpp:177-231"} {"id": "ext.d2dx.Metrics_GetRenderRect_letterbox_placement", "kind": "function", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog / Necrolis (D2DX)", "desc": "Computes on-screen _renderRect: integer-scales gameSize into desktop/window, centers it (offset=(dst-game*scale)/2); if margins exceed 16px falls back to non-integer scale filling width or height. This centered offset shifts only the final display blit, NOT world batches. | src: Rect rect{ (desktopSize.width - gameSize.width * scaleFactor) / 2, (desktopSize.height - gameSize.height * scaleFactor) / 2, gameSize.width * scaleFactor, gameSize.height * scaleFa", "source": ["https://github.com/Necrolis/d2dx-annihilus"], "locator": "Metrics.cpp:183-237"} {"id": "ext.d2dx.Text_Weather_MoP_also_uniform_category_gated", "kind": "note", "status": "sourced", "trust": "trusted", "module": "d2dx", "author": "bolrog / Necrolis (D2DX)", "desc": "TextMotionPredictor.GetOffset(textId,pos) offsets text; WeatherMotionPredictor.GetOffset offsets weather lines. Both additive screen offsets, not floor/wall specific. Feature flags: Unit+Weather MoP for Lod109d/112/113c/113d/114d; Text MoP only 113c/113d/114d.", "source": ["https://github.com/Necrolis/d2dx-annihilus"], "locator": "D2DXContext.cpp BeginDrawText/OnDrawLine", "value": "Unit+Weather: 109d,112,113c,113d,114d; Text: 113c,113d,114d"} {"id": "ext.(all).Offset_convention_base_relative", "kind": "note", "status": "sourced", "trust": "sourced", "module": "(all)", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "All FUNCPTR/VARPTR/ASMPTR offsets in this file are RELATIVE to the containing DLL's load base, not absolute VAs. d2bs adds the runtime module base. For 1.13c D2Client.dll the canonical base is 0x6FAB0000, so e.g. GetUnitX 0x1630 => ~0x6FAB1630. Negative numbers (e.g. -10010) are export ORDINALS resolved via GetProcAddress(MAKEINTRESOURCE(10010)), used for D2GFX/D2WIN/D2COMMON. | src: FUNCPTR/VARPTR/ASMPTR(MODULE, name, type, args, offset-or-ordinal)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "locator": "DEFINE_PTR macros"} {"id": "ext.D2GFX.D2GFX_DrawLine", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2GFX", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Draws a line between two screen points with color. | src: FUNCPTR(D2GFX, DrawLine, void __stdcall, (int X1, int Y1, int X2, int Y2, DWORD dwColor, DWORD dwUnk), -10010)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "locator": "ord -10010", "value": "-10010"} {"id": "ext.D2GFX.D2GFX_DrawRectangle", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2GFX", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Fills/draws a screen rectangle with color and transparency mode. | src: FUNCPTR(D2GFX, DrawRectangle, void __stdcall, (int X1, int Y1, int X2, int Y2, DWORD dwColor, DWORD dwTrans), -10014)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "locator": "ord -10014", "value": "-10014"} {"id": "ext.D2GFX.D2GFX_DrawAutomapCell2", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2GFX", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Renders a single automap cell/tile at screen xpos/ypos with two brightness values and a color table. Core automap-draw primitive. | src: FUNCPTR(D2GFX, DrawAutomapCell2, void __stdcall, (CellContext* context, DWORD xpos, DWORD ypos, DWORD bright2, DWORD bright, BYTE *coltab), -10041)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "locator": "ord -10041", "value": "-10041"} {"id": "ext.D2GFX.D2GFX_GetScreenSize", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2GFX", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Returns encoded screen resolution (packed WxH). Render viewport sizing. | src: FUNCPTR(D2GFX, GetScreenSize, DWORD __stdcall, (void), -10031)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "locator": "ord -10031", "value": "-10031"} {"id": "ext.D2GFX.D2GFX_GetHwnd", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2GFX", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Returns the game render window HWND. | src: FUNCPTR(D2GFX, GetHwnd, HWND __stdcall, (void), -10048)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "locator": "ord -10048", "value": "-10048"} {"id": "ext.D2WIN.D2WIN_DrawSprites", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2WIN", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Draws sprite batch (fastcall). Under 'D2Win Functions' header. | src: FUNCPTR(D2WIN, DrawSprites, void __fastcall, (void), 0x18750)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0x18750", "value": "0x18750"} {"id": "ext.D2WIN.D2WIN_TakeScreenshot", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2WIN", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Captures the current frame to a screenshot. | src: FUNCPTR(D2WIN, TakeScreenshot, void __fastcall, (), 0x17EB0)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0x17eb0", "value": "0x17EB0"} {"id": "ext.D2WIN.D2WIN_DrawText", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2WIN", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Draws a wide-char string at screen xPos/yPos with color. Primary on-screen text primitive. | src: FUNCPTR(D2WIN, DrawText, void __fastcall, (wchar_t *wStr, int xPos, int yPos, DWORD dwColor, DWORD dwUnk), -10150)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "locator": "ord -10150", "value": "-10150"} {"id": "ext.D2WIN.D2WIN_GetTextSize", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2WIN", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Measures pixel width (and font file no) of a string for layout/centering. | src: FUNCPTR(D2WIN, GetTextSize, DWORD __fastcall, (wchar_t *wStr, DWORD* dwWidth, DWORD* dwFileNo), -10177)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "locator": "ord -10177", "value": "-10177"} {"id": "ext.D2WIN.D2WIN_SetTextSize", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2WIN", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Selects the active font/text size for subsequent DrawText calls. | src: FUNCPTR(D2WIN, SetTextSize, DWORD __fastcall, (DWORD dwSize), -10184)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "locator": "ord -10184", "value": "-10184"} {"id": "ext.D2WIN.D2WIN_SplitText", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2WIN", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Word-wraps text to a pixel width, returning line array + count (text-layout helper). | src: FUNCPTR(D2WIN, SplitText, SplitText* __fastcall, (wchar_t* text, int* lineCount, int width), -10059)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "locator": "ord -10059", "value": "-10059"} {"id": "ext.D2WIN.D2WIN_FreeSplitText", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2WIN", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Frees a SplitText layout result. | src: FUNCPTR(D2WIN, FreeSplitText, void __fastcall, (SplitText* text), -10008)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "locator": "ord -10008", "value": "-10008"} {"id": "ext.D2WIN.D2WIN_SetControlText", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2WIN", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Sets the text of a UI Control (edit box/button). UI, borderline render. | src: FUNCPTR(D2WIN, SetControlText, void* __fastcall, (Control* box, wchar_t* txt), -10042)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "locator": "ord -10042", "value": "-10042"} {"id": "ext.D2WIN.D2WIN_FirstControl", "kind": "global", "status": "sourced", "trust": "sourced", "module": "D2WIN", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Head of the UI Control linked list. UI, borderline render. | src: VARPTR(D2WIN, FirstControl, Control*, 0x214A0)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0x214a0", "value": "0x214A0"} {"id": "ext.D2WIN.D2WIN_FocusedControl", "kind": "global", "status": "sourced", "trust": "sourced", "module": "D2WIN", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Currently focused UI Control. | src: VARPTR(D2WIN, FocusedControl, Control*, 0x214B0)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0x214b0", "value": "0x214B0"} {"id": "ext.D2CLIENT.D2CLIENT_GetUnitX", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Returns a unit's world X coordinate. Feeds world->screen projection. | src: FUNCPTR(D2CLIENT, GetUnitX, int __fastcall, (UnitAny* pUnit), 0x1630)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0x1630", "value": "0x1630"} {"id": "ext.D2CLIENT.D2CLIENT_GetUnitY", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Returns a unit's world Y coordinate. | src: FUNCPTR(D2CLIENT, GetUnitY, int __fastcall, (UnitAny* pUnit), 0x1660)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0x1660", "value": "0x1660"} {"id": "ext.D2CLIENT.D2CLIENT_ClearScreen", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Clears the screen/framebuffer. | src: FUNCPTR(D2CLIENT, ClearScreen, void __fastcall, (void), 0x48350)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0x48350", "value": "0x48350"} {"id": "ext.D2CLIENT.D2CLIENT_GetAutomapSize", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Returns automap size metric used for automap draw scaling. | src: FUNCPTR(D2CLIENT, GetAutomapSize, DWORD __stdcall, (void), 0x5F080)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0x5f080", "value": "0x5F080"} {"id": "ext.D2CLIENT.D2CLIENT_NewAutomapCell", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Allocates a new AutomapCell node. | src: FUNCPTR(D2CLIENT, NewAutomapCell, AutomapCell * __fastcall, (void), 0x5F6B0)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0x5f6b0", "value": "0x5F6B0"} {"id": "ext.D2CLIENT.D2CLIENT_AddAutomapCell", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Links an AutomapCell into an automap layer node list. | src: FUNCPTR(D2CLIENT, AddAutomapCell, void __fastcall, (AutomapCell *aCell, AutomapCell **node), 0x61320)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0x61320", "value": "0x61320"} {"id": "ext.D2CLIENT.D2CLIENT_RevealAutomapRoom", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Reveals a Room1's automap cells onto an AutomapLayer (with clip flag). Core map-reveal. | src: FUNCPTR(D2CLIENT, RevealAutomapRoom, void __stdcall, (Room1 *pRoom1, DWORD dwClipFlag, AutomapLayer *aLayer), 0x62580)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0x62580", "value": "0x62580"} {"id": "ext.D2CLIENT.D2CLIENT_InitAutomapLayer_I", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Initializes/returns the AutomapLayer for a given layer number. | src: FUNCPTR(D2CLIENT, InitAutomapLayer_I, AutomapLayer* __fastcall, (DWORD nLayerNo), 0x62710)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0x62710", "value": "0x62710"} {"id": "ext.D2CLIENT.D2CLIENT_ClickMap", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Handles a click at screen x,y (translates screen->world action). Coordinate-relevant. | src: FUNCPTR(D2CLIENT, ClickMap, void __stdcall, (DWORD MouseFlag, DWORD x, DWORD y, DWORD Type), 0x1BF20)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0x1bf20", "value": "0x1BF20"} {"id": "ext.D2CLIENT.D2CLIENT_GetMouseXOffset", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Returns the mouse X offset used in screen<->world coordinate math. | src: FUNCPTR(D2CLIENT, GetMouseXOffset, DWORD __fastcall, (void), 0x3F6C0)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0x3f6c0", "value": "0x3F6C0"} {"id": "ext.D2CLIENT.D2CLIENT_GetMouseYOffset", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Returns the mouse Y offset used in screen<->world coordinate math. | src: FUNCPTR(D2CLIENT, GetMouseYOffset, DWORD __fastcall, (void), 0x3F6D0)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0x3f6d0", "value": "0x3F6D0"} {"id": "ext.D2CLIENT.D2CLIENT_PrintGameString", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Prints a message to the on-screen game message area. | src: FUNCPTR(D2CLIENT, PrintGameString, void __stdcall, (wchar_t *wMessage, int nColor), 0x7D850)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0x7d850", "value": "0x7D850"} {"id": "ext.D2CLIENT.D2CLIENT_PrintPartyString", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Prints a party message to screen. | src: FUNCPTR(D2CLIENT, PrintPartyString, void __stdcall, (wchar_t *wMessage, int nColor), 0x7D610)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0x7d610", "value": "0x7D610"} {"id": "ext.D2CLIENT.D2CLIENT_DrawRectFrame", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Draws a rectangular frame on screen. | src: FUNCPTR(D2CLIENT, DrawRectFrame, void __fastcall, (DWORD Rect), 0xBE4C0)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0xbe4c0", "value": "0xBE4C0"} {"id": "ext.D2CLIENT.D2CLIENT_ScreenSizeY", "kind": "global", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Current viewport height in pixels. | src: VARPTR(D2CLIENT, ScreenSizeY, DWORD, 0xDBC4C)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0xdbc4c", "value": "0xDBC4C"} {"id": "ext.D2CLIENT.D2CLIENT_CursorHoverX", "kind": "global", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Screen X of the hovered cell/cursor target. | src: VARPTR(D2CLIENT, CursorHoverX, DWORD, 0xE0EB8)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0xe0eb8", "value": "0xE0EB8"} {"id": "ext.D2CLIENT.D2CLIENT_CursorHoverY", "kind": "global", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Screen Y of the hovered cell/cursor target. | src: VARPTR(D2CLIENT, CursorHoverY, DWORD, 0xE0EBC)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0xe0ebc", "value": "0xE0EBC"} {"id": "ext.D2CLIENT.D2CLIENT_MouseX", "kind": "global", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Current mouse cursor X in screen pixels. | src: VARPTR(D2CLIENT, MouseX, DWORD, 0x11B828)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0x11b828", "value": "0x11B828"} {"id": "ext.D2CLIENT.D2CLIENT_MouseY", "kind": "global", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Current mouse cursor Y in screen pixels. | src: VARPTR(D2CLIENT, MouseY, DWORD, 0x11B824)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0x11b824", "value": "0x11B824"} {"id": "ext.D2CLIENT.D2CLIENT_ViewportX", "kind": "global", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Viewport/gamewindow X extent (int). Used with ViewportY for world->screen shift. | src: VARPTR(D2CLIENT, ViewportX, int, 0x119960)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0x119960", "value": "0x119960"} {"id": "ext.D2CLIENT.D2CLIENT_ViewportY", "kind": "global", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Viewport/gamewindow Y extent (int). | src: VARPTR(D2CLIENT, ViewportY, int, 0x11995C)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0x11995c", "value": "0x11995C"} {"id": "ext.D2CLIENT.D2CLIENT_AutomapOn", "kind": "global", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Nonzero when the automap is displayed. | src: VARPTR(D2CLIENT, AutomapOn, DWORD, 0xFADA8)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0xfada8", "value": "0xFADA8"} {"id": "ext.D2CLIENT.D2CLIENT_AutomapMode", "kind": "global", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Automap display mode (full/mini/etc). | src: VARPTR(D2CLIENT, AutomapMode, int, 0xF16B0)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0xf16b0", "value": "0xF16B0"} {"id": "ext.D2CLIENT.D2CLIENT_Offset", "kind": "global", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "POINT screen offset applied when drawing (render/scroll origin). Coordinate-shift global. | src: VARPTR(D2CLIENT, Offset, POINT, 0x11C1F8)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0x11c1f8", "value": "0x11C1F8"} {"id": "ext.D2CLIENT.D2CLIENT_AutomapLayer", "kind": "global", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "Pointer to the active AutomapLayer being drawn. | src: VARPTR(D2CLIENT, AutomapLayer, AutomapLayer*, 0x11C1C4)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0x11c1c4", "value": "0x11C1C4"} {"id": "ext.D2CLIENT.D2CLIENT_BodyClickTable_ASM", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "ASM patch anchor near the cursor/hover click-target table (adjacent to CursorHoverX/Y). | src: ASMPTR(D2CLIENT, BodyClickTable, 0xE0EC4)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0xe0ec4", "value": "0xE0EC4"} {"id": "ext.D2CLIENT.D2CLIENT_ClickMap_I_ASM", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "ASM patch anchor for click-to-move handling (adjacent to AutomapOn 0xFADA8). | src: ASMPTR(D2CLIENT, ClickMap_I, 0xFADA4)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0xfada4", "value": "0xFADA4"} {"id": "ext.D2CLIENT.D2CLIENT_ClickMap_II_ASM", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "ASM patch anchor for click-map coordinate handling. | src: ASMPTR(D2CLIENT, ClickMap_II, 0x11C4D8)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0x11c4d8", "value": "0x11C4D8"} {"id": "ext.D2CLIENT.D2CLIENT_ClickMap_III_ASM", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "ASM patch anchor for click-map (near GetMouseX/YOffset 0x3F6C0/0x3F6D0). | src: ASMPTR(D2CLIENT, ClickMap_III, 0x3F5F0)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0x3f5f0", "value": "0x3F5F0"} {"id": "ext.D2CLIENT.D2CLIENT_ClickMap_IV_ASM", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "d2bs community (ds-hwang/noah- patch-113)", "desc": "ASM patch anchor inside ClickMap (0x1BF20 + 0x79). | src: ASMPTR(D2CLIENT, ClickMap_IV, 0x1BF99)", "source": ["https://raw.githubusercontent.com/ds-hwang/d2bs/master/branches/patch-113/D2Ptrs.h"], "rva": "0x1bf99", "value": "0x1BF99"} {"id": "ext.macro_format", "kind": "note", "status": "sourced", "trust": "sourced", "module": "", "author": "SlashDiablo BH / planqi", "desc": "The file uses three macros, each ending with a DUAL offset pair: the 1.13c value FIRST, then the 1.13d value. VARPTR(DLL, Name, Type, off_113c, off_113d) for globals; FUNCPTR(DLL, Name, RetType/callconv, (args), val_113c, val_113d) and ASMPTR(DLL, Name, ..., val_113c, val_113d) for functions. NEGATIVE values are export ORDINALS (e.g. -10079); POSITIVE hex values are direct in-DLL OFFSETS (e.g. 0x18750). This c-then-d ordering is the rebasing key. | src: VARPTR(D2CLIENT, ScreenSizeX, DWORD, 0xDBC48, 0xF7034)", "source": ["https://raw.githubusercontent.com/planqi/slashdiablo-maphack/master/BH/D2Ptrs.h"], "locator": "D2Ptrs.h", "value": "1.13c value first, 1.13d value second"} {"id": "ext.D2CLIENT.ScreenSizeY", "kind": "global", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "SlashDiablo BH / planqi", "desc": "Screen height global (DWORD). | src: VARPTR(D2CLIENT, ScreenSizeY, DWORD, 0xDBC4C, 0xF7038)", "source": ["https://raw.githubusercontent.com/planqi/slashdiablo-maphack/master/BH/D2Ptrs.h"], "rva": "0xdbc4c", "value": "113c=0xDBC4C, 113d=0xF7038"} {"id": "ext.D2CLIENT.CursorHoverX", "kind": "global", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "SlashDiablo BH / planqi", "desc": "Cursor hover X coordinate (DWORD). | src: VARPTR(D2CLIENT, CursorHoverX, DWORD, 0xE0EB8, 0xEE4AC)", "source": ["https://raw.githubusercontent.com/planqi/slashdiablo-maphack/master/BH/D2Ptrs.h"], "rva": "0xe0eb8", "value": "113c=0xE0EB8, 113d=0xEE4AC"} {"id": "ext.D2CLIENT.CursorHoverY", "kind": "global", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "SlashDiablo BH / planqi", "desc": "Cursor hover Y coordinate (DWORD). | src: VARPTR(D2CLIENT, CursorHoverY, DWORD, 0xE0EBC, 0xEE4B0)", "source": ["https://raw.githubusercontent.com/planqi/slashdiablo-maphack/master/BH/D2Ptrs.h"], "rva": "0xe0ebc", "value": "113c=0xE0EBC, 113d=0xEE4B0"} {"id": "ext.D2CLIENT.MouseX", "kind": "global", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "SlashDiablo BH / planqi", "desc": "Mouse X screen position (DWORD). | src: VARPTR(D2CLIENT, MouseX, DWORD, 0x11B828, 0x11C950)", "source": ["https://raw.githubusercontent.com/planqi/slashdiablo-maphack/master/BH/D2Ptrs.h"], "rva": "0x11b828", "value": "113c=0x11B828, 113d=0x11C950"} {"id": "ext.D2CLIENT.MouseY", "kind": "global", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "SlashDiablo BH / planqi", "desc": "Mouse Y screen position (DWORD). | src: VARPTR(D2CLIENT, MouseY, DWORD, 0x11B824, 0x11C94C)", "source": ["https://raw.githubusercontent.com/planqi/slashdiablo-maphack/master/BH/D2Ptrs.h"], "rva": "0x11b824", "value": "113c=0x11B824, 113d=0x11C94C"} {"id": "ext.D2CLIENT.MouseOffsetX", "kind": "global", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "SlashDiablo BH / planqi", "desc": "Mouse offset X (int) — screen-to-world/viewport offset. | src: VARPTR(D2CLIENT, MouseOffsetX, int, 0x119960, 0x106844)", "source": ["https://raw.githubusercontent.com/planqi/slashdiablo-maphack/master/BH/D2Ptrs.h"], "rva": "0x119960", "value": "113c=0x119960, 113d=0x106844"} {"id": "ext.D2CLIENT.MouseOffsetY", "kind": "global", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "SlashDiablo BH / planqi", "desc": "Mouse offset Y (int) — screen-to-world/viewport offset. | src: VARPTR(D2CLIENT, MouseOffsetY, int, 0x11995C, 0x106840)", "source": ["https://raw.githubusercontent.com/planqi/slashdiablo-maphack/master/BH/D2Ptrs.h"], "rva": "0x11995c", "value": "113c=0x11995C, 113d=0x106840"} {"id": "ext.D2CLIENT.Offset", "kind": "global", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "SlashDiablo BH / planqi", "desc": "Screen render Offset (POINT struct) — the world-to-screen scroll/camera offset used when drawing units and automap. | src: VARPTR(D2CLIENT, Offset, POINT, 0x11C1F8, 0x11CF5C)", "source": ["https://raw.githubusercontent.com/planqi/slashdiablo-maphack/master/BH/D2Ptrs.h"], "rva": "0x11c1f8", "value": "113c=0x11C1F8, 113d=0x11CF5C"} {"id": "ext.D2CLIENT.PanelOffsetX", "kind": "global", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "SlashDiablo BH / planqi", "desc": "Panel offset X (int) — horizontal shift applied when side panels (inventory/skill) are open. Directly relevant to viewport shift. | src: VARPTR(D2CLIENT, PanelOffsetX, int, 0x11B9A0, 0x11D354)", "source": ["https://raw.githubusercontent.com/planqi/slashdiablo-maphack/master/BH/D2Ptrs.h"], "rva": "0x11b9a0", "value": "113c=0x11B9A0, 113d=0x11D354"} {"id": "ext.D2CLIENT.xShake", "kind": "global", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "SlashDiablo BH / planqi", "desc": "Screen-shake X offset (int) applied to render position. | src: VARPTR(D2CLIENT, xShake, int, 0x11BF00, 0x11CA6C)", "source": ["https://raw.githubusercontent.com/planqi/slashdiablo-maphack/master/BH/D2Ptrs.h"], "rva": "0x11bf00", "value": "113c=0x11BF00, 113d=0x11CA6C"} {"id": "ext.D2CLIENT.yShake", "kind": "global", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "SlashDiablo BH / planqi", "desc": "Screen-shake Y offset (int) applied to render position. | src: VARPTR(D2CLIENT, yShake, int, 0x10B9DC, 0xFC3DC)", "source": ["https://raw.githubusercontent.com/planqi/slashdiablo-maphack/master/BH/D2Ptrs.h"], "rva": "0x10b9dc", "value": "113c=0x10B9DC, 113d=0xFC3DC"} {"id": "ext.D2CLIENT.AutomapOn", "kind": "global", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "SlashDiablo BH / planqi", "desc": "Automap-visible flag (DWORD). | src: VARPTR(D2CLIENT, AutomapOn, DWORD, 0xFADA8, 0x11C8B8)", "source": ["https://raw.githubusercontent.com/planqi/slashdiablo-maphack/master/BH/D2Ptrs.h"], "rva": "0xfada8", "value": "113c=0xFADA8, 113d=0x11C8B8"} {"id": "ext.D2CLIENT.AutomapMode", "kind": "global", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "SlashDiablo BH / planqi", "desc": "Automap display mode (int). | src: VARPTR(D2CLIENT, AutomapMode, int, 0xF16B0, 0xF34F8)", "source": ["https://raw.githubusercontent.com/planqi/slashdiablo-maphack/master/BH/D2Ptrs.h"], "rva": "0xf16b0", "value": "113c=0xF16B0, 113d=0xF34F8"} {"id": "ext.D2CLIENT.AutomapLayer", "kind": "global", "status": "sourced", "trust": "sourced", "module": "D2CLIENT", "author": "SlashDiablo BH / planqi", "desc": "Pointer to current AutomapLayer* — root of the automap cell list that gets drawn. | src: VARPTR(D2CLIENT, AutomapLayer, AutomapLayer*, 0x11C1C4, 0x11CF28)", "source": ["https://raw.githubusercontent.com/planqi/slashdiablo-maphack/master/BH/D2Ptrs.h"], "rva": "0x11c1c4", "value": "113c=0x11C1C4, 113d=0x11CF28"} {"id": "ext.D2GFX.VideoMode_2", "kind": "global", "status": "sourced", "trust": "sourced", "module": "D2GFX", "author": "SlashDiablo BH / planqi", "desc": "Current video/render mode (WORD) — DDraw/D3D/Glide selector. | src: VARPTR(D2GFX, VideoMode, WORD, 0x11258, 0x14A38)", "source": ["https://raw.githubusercontent.com/planqi/slashdiablo-maphack/master/BH/D2Ptrs.h"], "rva": "0x11258", "value": "113c=0x11258, 113d=0x14A38"} {"id": "ext.D2GFX.DrawLine", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2GFX", "author": "SlashDiablo BH / planqi", "desc": "Draws a line. Args (int X1,int Y1,int X2,int Y2,DWORD dwColor,DWORD dwUnk), __stdcall. Dual = export ordinals. | src: FUNCPTR(D2GFX, DrawLine, void __stdcall, (int X1, int Y1, int X2, int Y2, DWORD dwColor, DWORD dwUnk), -10010, -10013)", "source": ["https://raw.githubusercontent.com/planqi/slashdiablo-maphack/master/BH/D2Ptrs.h"], "locator": "D2GFX ord -10010 / -10013", "value": "113c=-10010, 113d=-10013"} {"id": "ext.D2GFX.DrawRectangle_2", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2GFX", "author": "SlashDiablo BH / planqi", "desc": "Draws a filled/trans rectangle. Args (int X1,int Y1,int X2,int Y2,DWORD dwColor,DWORD dwTrans), __stdcall. | src: FUNCPTR(D2GFX, DrawRectangle, void __stdcall, (int X1, int Y1, int X2, int Y2, DWORD dwColor, DWORD dwTrans), -10014, -10028)", "source": ["https://raw.githubusercontent.com/planqi/slashdiablo-maphack/master/BH/D2Ptrs.h"], "locator": "D2GFX ord -10014 / -10028", "value": "113c=-10014, 113d=-10028"} {"id": "ext.D2GFX.DrawAutomapCell", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2GFX", "author": "SlashDiablo BH / planqi", "desc": "Core automap-cell blitter. ASMPTR. Args (CellContext *context,DWORD xpos,DWORD ypos,RECT *cliprect,DWORD bright), __stdcall. | src: ASMPTR(D2GFX, DrawAutomapCell, void __stdcall, (CellContext *context, DWORD xpos, DWORD ypos, RECT *cliprect, DWORD bright), -10079, -10060)", "source": ["https://raw.githubusercontent.com/planqi/slashdiablo-maphack/master/BH/D2Ptrs.h"], "locator": "D2GFX ord -10079 / -10060 (ASMPTR)", "value": "113c=-10079, 113d=-10060"} {"id": "ext.D2GFX.DrawAutomapCell2", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2GFX", "author": "SlashDiablo BH / planqi", "desc": "Second automap-cell draw variant. Args (CellContext* context,DWORD xpos,DWORD ypos,DWORD bright2,DWORD bright,BYTE *coltab), __stdcall. | src: FUNCPTR(D2GFX, DrawAutomapCell2, void __stdcall, (CellContext* context, DWORD xpos, DWORD ypos, DWORD bright2, DWORD bright, BYTE *coltab), -10041, -10042)", "source": ["https://raw.githubusercontent.com/planqi/slashdiablo-maphack/master/BH/D2Ptrs.h"], "locator": "D2GFX ord -10041 / -10042", "value": "113c=-10041, 113d=-10042"} {"id": "ext.D2GFX.DrawCellContextEx", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2GFX", "author": "SlashDiablo BH / planqi", "desc": "Draws a cell context (sprite) with transparency/color. Args (CellContext *context,int Xpos,int Ypos,int dwl,int nTransLvl,BYTE Color), __stdcall. | src: FUNCPTR(D2GFX, DrawCellContextEx, void __stdcall, (CellContext *context, int Xpos, int Ypos, int dwl, int nTransLvl, BYTE Color), -10019, -10067)", "source": ["https://raw.githubusercontent.com/planqi/slashdiablo-maphack/master/BH/D2Ptrs.h"], "locator": "D2GFX ord -10019 / -10067", "value": "113c=-10019, 113d=-10067"} {"id": "ext.D2GFX.GetScreenSize", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2GFX", "author": "SlashDiablo BH / planqi", "desc": "Returns the current screen size. __stdcall (void). Render/viewport query. | src: FUNCPTR(D2GFX, GetScreenSize, DWORD __stdcall, (void), -10031, -10012)", "source": ["https://raw.githubusercontent.com/planqi/slashdiablo-maphack/master/BH/D2Ptrs.h"], "locator": "D2GFX ord -10031 / -10012", "value": "113c=-10031, 113d=-10012"} {"id": "ext.D2WIN.DrawSprites", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2WIN", "author": "SlashDiablo BH / planqi", "desc": "Batched sprite draw. __fastcall (void). NOTE: dual values are DIRECT OFFSETS (positive hex), not ordinals — key rebasing distinction. | src: FUNCPTR(D2WIN, DrawSprites, void __fastcall, (void), 0x18750, 0xEAA0)", "source": ["https://raw.githubusercontent.com/planqi/slashdiablo-maphack/master/BH/D2Ptrs.h"], "rva": "0x18750", "value": "113c=0x18750, 113d=0xEAA0"} {"id": "ext.D2WIN.DrawCellFile", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2WIN", "author": "SlashDiablo BH / planqi", "desc": "Draws a CellFile sprite. Args (CellFile * pCellFile,int xPos,int yPos,int div,int trans,int Color), __fastcall. | src: FUNCPTR(D2WIN, DrawCellFile, void __fastcall, (CellFile * pCellFile, int xPos, int yPos, int div, int trans, int Color), -10138, -10172)", "source": ["https://raw.githubusercontent.com/planqi/slashdiablo-maphack/master/BH/D2Ptrs.h"], "locator": "D2WIN ord -10138 / -10172", "value": "113c=-10138, 113d=-10172"} {"id": "ext.D2WIN.DrawText", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2WIN", "author": "SlashDiablo BH / planqi", "desc": "Draws a unicode text string. Args (const wchar_t *wStr,int xPos,int yPos,DWORD dwColor,DWORD dwUnk), __fastcall. | src: FUNCPTR(D2WIN, DrawText, void __fastcall, (const wchar_t *wStr, int xPos, int yPos, DWORD dwColor, DWORD dwUnk), -10150, -10076)", "source": ["https://raw.githubusercontent.com/planqi/slashdiablo-maphack/master/BH/D2Ptrs.h"], "locator": "D2WIN ord -10150 / -10076", "value": "113c=-10150, 113d=-10076"} {"id": "ext.D2WIN.DrawTextBuffer", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2WIN", "author": "SlashDiablo BH / planqi", "desc": "Text-buffer draw routine. ASMPTR with DIRECT OFFSETS (positive hex), not ordinals. | src: ASMPTR(D2WIN, DrawTextBuffer, 0x12940, 0x134D0)", "source": ["https://raw.githubusercontent.com/planqi/slashdiablo-maphack/master/BH/D2Ptrs.h"], "rva": "0x12940", "value": "113c=0x12940, 113d=0x134D0"} {"id": "ext.D2WIN.GetTextSize", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2WIN", "author": "SlashDiablo BH / planqi", "desc": "Measures text width/height. Args (wchar_t *wStr,DWORD* dwWidth,DWORD* dwFileNo), __fastcall. | src: FUNCPTR(D2WIN, GetTextSize, DWORD __fastcall, (wchar_t *wStr, DWORD* dwWidth, DWORD* dwFileNo), -10177, -10179)", "source": ["https://raw.githubusercontent.com/planqi/slashdiablo-maphack/master/BH/D2Ptrs.h"], "locator": "D2WIN ord -10177 / -10179", "value": "113c=-10177, 113d=-10179"} {"id": "ext.D2WIN.SetTextSize", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2WIN", "author": "SlashDiablo BH / planqi", "desc": "Sets the active font/text size. Args (DWORD dwSize), __fastcall. | src: FUNCPTR(D2WIN, SetTextSize, DWORD __fastcall, (DWORD dwSize), -10184, -10047)", "source": ["https://raw.githubusercontent.com/planqi/slashdiablo-maphack/master/BH/D2Ptrs.h"], "locator": "D2WIN ord -10184 / -10047", "value": "113c=-10184, 113d=-10047"} {"id": "ext.D2WIN.GetTextWidthFileNo", "kind": "function", "status": "sourced", "trust": "sourced", "module": "D2WIN", "author": "SlashDiablo BH / planqi", "desc": "Text width + file-number query. Same ordinals as GetTextSize (-10177/-10179) — aliased export. Args (wchar_t *wStr,DWORD* dwWidth,DWORD* dwFileNo), __fastcall. | src: FUNCPTR(D2WIN, GetTextWidthFileNo, DWORD __fastcall, (wchar_t *wStr, DWORD* dwWidth, DWORD* dwFileNo), -10177, -10179)", "source": ["https://raw.githubusercontent.com/planqi/slashdiablo-maphack/master/BH/D2Ptrs.h"], "locator": "D2WIN ord -10177 / -10179", "value": "113c=-10177, 113d=-10179"} {"id": "struct.CellFile", "kind": "struct", "status": "sourced", "trust": "sourced", "module": "D2 client (DC6/sprite file)", "author": "d2bs community (noah-)", "desc": "Sprite/cell file container. dwVersion 0x00; an anonymous struct at 0x04 { WORD dwFlags; BYTE mylastcol; BYTE mytabno:1 }; eFormat 0x08; termination 0x0C; numdirs 0x10; numcells 0x14; GfxCell* cells[255] at 0x18 (array of pointers to decoded GfxCell frames). | src: DWORD dwVersion; //0x00 | struct{WORD dwFlags;BYTE mylastcol;BYTE mytabno:1;}; //0x04 | DWORD eFormat; //0x08 | DWORD termination; //0x0C | DWORD numdirs; //0x10 | DWORD numcells; ", "source": ["https://raw.githubusercontent.com/noah-/d2bs/master/D2Structs.h"], "locator": "D2Structs.h CellFile"} {"id": "struct.AutomapLayer2", "kind": "struct", "status": "sourced", "trust": "sourced", "module": "D2 client (automap)", "author": "d2bs community (noah-)", "desc": "Small automap layer variant: _1[2] 0x00; nLayerNo at 0x08. | src: DWORD _1[2]; //0x00 | DWORD nLayerNo; //0x08", "source": ["https://raw.githubusercontent.com/noah-/d2bs/master/D2Structs.h"], "locator": "D2Structs.h AutomapLayer2"} {"id": "struct.ItemPath", "kind": "struct", "status": "sourced", "trust": "sourced", "module": "D2 client", "author": "d2bs community (noah-)", "desc": "Item position path head: _1[3] 0x00; dwPosX 0x0C; dwPosY 0x10 (DWORD tile coords). 'Use Path for the rest.' | src: DWORD _1[3]; //0x00 | DWORD dwPosX; //0x0C | DWORD dwPosY; //0x10", "source": ["https://raw.githubusercontent.com/noah-/d2bs/master/D2Structs.h"], "locator": "D2Structs.h ItemPath"} {"id": "struct.ObjectPath", "kind": "struct", "status": "sourced", "trust": "sourced", "module": "D2 client", "author": "d2bs community (noah-)", "desc": "Object position path head: pRoom1 0x00; _1[2] 0x04; dwPosX 0x0C; dwPosY 0x10. 'Leaving rest undefined, use Path.' | src: Room1* pRoom1; //0x00 | DWORD _1[2]; //0x04 | DWORD dwPosX; //0x0C | DWORD dwPosY; //0x10", "source": ["https://raw.githubusercontent.com/noah-/d2bs/master/D2Structs.h"], "locator": "D2Structs.h ObjectPath"} {"id": "struct.CollMap", "kind": "struct", "status": "sourced", "trust": "sourced", "module": "D2 client (collision/map)", "author": "d2bs community (noah-)", "desc": "Collision map grid. dwPosGameX 0x00; dwPosGameY 0x04; dwSizeGameX 0x08; dwSizeGameY 0x0C; dwPosRoomX 0x10; dwPosRoomY 0x14; dwSizeRoomX 0x18; dwSizeRoomY 0x1C; pMapStart 0x20 (WORD*); pMapEnd 0x22 (WORD*). Game vs Room coordinate spaces both present; pMapStart is the walkability grid used for map rendering/pathing. | src: DWORD dwPosGameX;0x00 | DWORD dwPosGameY;0x04 | DWORD dwSizeGameX;0x08 | DWORD dwSizeGameY;0x0C | DWORD dwPosRoomX;0x10 | DWORD dwPosRoomY;0x14 | DWORD dwSizeRoomX;0x18 | DWORD dwS", "source": ["https://raw.githubusercontent.com/noah-/d2bs/master/D2Structs.h"], "locator": "D2Structs.h CollMap"} {"id": "struct.ObjectTxt", "kind": "struct", "status": "sourced", "trust": "sourced", "module": "D2 client (TXT)", "author": "d2bs community (noah-)", "desc": "Object type record. Render-relevant: nOrientation at 0x14C (draw orientation) and nAutoMap at 0x1BB (automap icon index). Also szName 0x00, wszName 0x40, nSelectable0 0xC4, nSubClass 0x166, nParm0 0x178, nPopulateFn 0x1B2, nOperateFn 0x1B3. | src: BYTE nOrientation; //0x14C | DWORD nAutoMap; //0x1BB", "source": ["https://raw.githubusercontent.com/noah-/d2bs/master/D2Structs.h"], "locator": "D2Structs.h ObjectTxt"} {"id": "struct.RosterUnit", "kind": "struct", "status": "sourced", "trust": "sourced", "module": "", "author": "d2bs community (noah-)", "desc": "Party roster entry. szName[16] 0x00; dwUnitId 0x10; dwClassId 0x1C; wLevel 0x20; wPartyId 0x22; dwLevelId 0x24; Xpos 0x28; Ypos 0x2C; dwPartyFlags 0x30; szName2[16] 0x66; pNext 0x80. Xpos/Ypos are party-member map coords (minimap/render). | src: DWORD Xpos;0x28 | DWORD Ypos;0x2C | DWORD dwLevelId;0x24", "source": ["https://raw.githubusercontent.com/noah-/d2bs/master/D2Structs.h"], "locator": "D2Structs.h RosterUnit (pack(1))"} {"id": "ext.pragma_pack_context_for_world_structs", "kind": "note", "status": "sourced", "trust": "sourced", "module": "", "author": "d2bs community (noah-)", "desc": "CRITICAL: Level, Room2, CollMap, PresetUnit, RoomTile, RosterUnit, BnetData, PlayerData, Waypoint, QuestInfo are inside a #pragma pack(push)/pack(1) region — their true in-memory byte spacing is packed (no natural alignment padding); trust the explicit hex offset comments, not sizeof-based math. GfxCell, CellFile, CellContext, AutomapCell/Layer, UnitAny, Room1, Act, ActMisc, Control are OUTSIDE pack(1) (default alignment). | src: #pragma pack(push) #pragma pack(1) ... #pragma pack(pop)", "source": ["https://raw.githubusercontent.com/noah-/d2bs/master/D2Structs.h"], "locator": "D2Structs.h #pragma pack(1) block", "value": "pack(1) wraps BnetData..Room2; second pack(1) wraps NPCMenu,OverheadMsg"} {"id": "ext.D2Client (uses D2Common exports).UNITS_GetDrawingPosition_non_perspective_branc", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2Client (uses D2Common exports)", "author": "kidpaddle94 / Necrolis (Phrozen Keep t=62562)", "desc": "Non-perspective (isometric) screen position of a unit. Two-line math: X offset minus (camera-X minus secondary-X), Y offset minus camera-Y. This is the core render-position formula for the FOCUS constants. | src: pPos->nX = D2COMMON_GetUnitOffsetX(pUnit) - (*D2CLIENT_6FBC9960 - *D2CLIENT_6FBCC418);\npPos->nY = D2COMMON_GetUnitOffsetY(pUnit) - *D2CLIENT_6FBC995C;", "source": ["https://d2mods.info/forum/viewtopic.php?t=62562"], "locator": "guarded by !D2GFX_CheckPerspective()"} {"id": "ext.D2Client (uses D2Gfx + D2Common exports).UNITS_GetDrawingPosition_perspective_branch", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2Client (uses D2Gfx + D2Common exports)", "author": "kidpaddle94 / Necrolis (Phrozen Keep t=62562)", "desc": "Perspective-mode screen position. Reads unit world position (not offset), guards with D2GFX_CheckPerspectivePosition, transforms via D2GFX_AdjustPerspectivePosition, then applies +/-256 X shift based on UI panel state. | src: int nX = D2COMMON_GetUnitPositionX(pUnit);\nint nY = D2COMMON_GetUnitPositionY(pUnit);\nint nAdjustX = 0;\nint nAdjustY = 0;\nif (!D2GFX_CheckPerspectivePosition(nX, nY)) return FALSE;", "source": ["https://d2mods.info/forum/viewtopic.php?t=62562"], "locator": "else branch when D2GFX_CheckPerspective() is true"} {"id": "ext.D2Client.UNITS_GetDrawingPosition_full_signature", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2Client", "author": "kidpaddle94 / Necrolis (Phrozen Keep t=62562)", "desc": "Signature and null-guard of the reconstructed C function that kidpaddle94 describes as a slightly modified version of what the unit-hover handler uses. Returns FALSE on null args or failed perspective-position check. | src: BOOL __fastcall UNITS_GetDrawingPosition(D2UnitStrc* pUnit, D2CoordStrc* pPos)\n{\n if (!pUnit || !pPos) return FALSE;", "source": ["https://d2mods.info/forum/viewtopic.php?t=62562"], "locator": "BOOL __fastcall(D2UnitStrc* pUnit, D2CoordStrc* pPos)"} {"id": "ext.D2Client.UNITHOVER_Main", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2Client", "author": "kidpaddle94 / Necrolis (Phrozen Keep t=62562)", "desc": "Unit-hover main handler. Comment notes it 'originally had pUnit arg'; reconstructed as void __fastcall pulling the unit from D2CLIENT_GetSelectedUnit(). Writes gnHoverX/gnHoverY then dispatches by pUnit->dwType. | src: /*\n\tFunction:\t\tUNITHOVER_Main\n\tAddress:\t\tD2Client.0xC0D30\n\tNotes:\t\t\toriginally had pUnit arg\n*/\nvoid __fastcall UNITHOVER_Main()", "source": ["https://d2mods.info/forum/viewtopic.php?t=62562"], "rva": "0xc0d30"} {"id": "ext.D2Client.UNITHOVER_Main_non_perspective_hover_math", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2Client", "author": "kidpaddle94 / Necrolis (Phrozen Keep t=62562)", "desc": "Non-perspective hover coordinate math. IDENTICAL X formula to UNITS_GetDrawingPosition, but Y subtracts an extra 8: (*D2CLIENT_6FBC995C - 8). This is the key difference from the drawing-position formula. | src: *D2CLIENT_gnHoverX = D2COMMON_GetUnitOffsetX(pUnit) - (*D2CLIENT_6FBC9960 - *D2CLIENT_6FBCC418);\n*D2CLIENT_gnHoverY = D2COMMON_GetUnitOffsetY(pUnit) - (*D2CLIENT_6FBC995C - 8);", "source": ["https://d2mods.info/forum/viewtopic.php?t=62562"], "rva": "0xc0d30"} {"id": "ext.D2Client.UNITHOVER_Main_perspective_hover_math", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2Client", "author": "kidpaddle94 / Necrolis (Phrozen Keep t=62562)", "desc": "Perspective hover math. Same CheckPerspectivePosition guard + AdjustPerspectivePosition + UISTATE +/-256 X shift as the drawing-position function, but the final Y adds 16: gnHoverY = nAdjustY + 16. | src: if (!D2GFX_CheckPerspectivePosition(nX, nY)) return;\nD2GFX_AdjustPerspectivePosition(nX, nY, 0, &nAdjustX, &nAdjustY);\nswitch (*D2CLIENT_gnGlobalUiState)\n{\n case UISTATE_RIGHT: ", "source": ["https://d2mods.info/forum/viewtopic.php?t=62562"], "rva": "0xc0d30"} {"id": "ext.D2Client.D2CLIENT_6FBC9960", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2Client", "author": "kidpaddle94 / Necrolis (Phrozen Keep t=62562)", "desc": "Camera/viewport X reference. Used as the minuend inside the X screen-offset term (*D2CLIENT_6FBC9960 - *D2CLIENT_6FBCC418) in BOTH UNITS_GetDrawingPosition and UNITHOVER_Main non-perspective branches. Dereferenced pointer to an int. | src: (*D2CLIENT_6FBC9960 - *D2CLIENT_6FBCC418)", "source": ["https://d2mods.info/forum/viewtopic.php?t=62562"], "locator": "6FBC9960 (D2Client, absolute VA, dereferenced as *D2CLIENT_6FBC9960)"} {"id": "ext.D2Client.D2CLIENT_6FBCC418", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2Client", "author": "kidpaddle94 / Necrolis (Phrozen Keep t=62562)", "desc": "Secondary X offset. Subtrahend in the X term (*D2CLIENT_6FBC9960 - *D2CLIENT_6FBCC418). Present in both non-perspective X formulas (drawing-position and hover). | src: (*D2CLIENT_6FBC9960 - *D2CLIENT_6FBCC418)", "source": ["https://d2mods.info/forum/viewtopic.php?t=62562"], "locator": "6FBCC418 (D2Client, absolute VA, dereferenced as *D2CLIENT_6FBCC418)"} {"id": "ext.D2Client.D2CLIENT_6FBC995C", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2Client", "author": "kidpaddle94 / Necrolis (Phrozen Keep t=62562)", "desc": "Camera/viewport Y reference. In drawing-position: nY = OffsetY - *D2CLIENT_6FBC995C. In hover: gnHoverY = OffsetY - (*D2CLIENT_6FBC995C - 8) (extra -8). | src: pPos->nY = D2COMMON_GetUnitOffsetY(pUnit) - *D2CLIENT_6FBC995C;", "source": ["https://d2mods.info/forum/viewtopic.php?t=62562"], "locator": "6FBC995C (D2Client, absolute VA, dereferenced as *D2CLIENT_6FBC995C)"} {"id": "ext.D2Gfx.D2GFX_CheckPerspective", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2Gfx", "author": "kidpaddle94 / Necrolis (Phrozen Keep t=62562)", "desc": "Boolean gate selecting perspective vs isometric branch. Returns nonzero when D3D perspective (depth distortion) mode is active. No numeric address given in the thread. | src: if (!D2GFX_CheckPerspective())", "source": ["https://d2mods.info/forum/viewtopic.php?t=62562"], "locator": "D2Gfx export (name only; no ordinal/offset given in thread)"} {"id": "ext.D2Gfx.D2GFX_CheckPerspectivePosition", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2Gfx", "author": "kidpaddle94 / Necrolis (Phrozen Keep t=62562)", "desc": "Validates a world (nX,nY) coordinate for perspective transform; failure aborts (return FALSE / return). Called before D2GFX_AdjustPerspectivePosition. | src: if (!D2GFX_CheckPerspectivePosition(nX, nY)) return FALSE;", "source": ["https://d2mods.info/forum/viewtopic.php?t=62562"], "locator": "D2Gfx export (name only; no ordinal/offset given)"} {"id": "ext.D2Gfx.D2GFX_AdjustPerspectivePosition", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2Gfx", "author": "kidpaddle94 / Necrolis (Phrozen Keep t=62562)", "desc": "The perspective-adjust entry point. Signature as used: (int nX, int nY, int 0, int* pAdjustX, int* pAdjustY) — takes world X/Y and a literal 0 third arg, writes screen-adjusted X/Y through the two out-pointers. Output then gets the UISTATE +/-256 X correction. | src: D2GFX_AdjustPerspectivePosition(nX, nY, 0, &nAdjustX, &nAdjustY);", "source": ["https://d2mods.info/forum/viewtopic.php?t=62562"], "locator": "D2Gfx export (name only; no ordinal/offset given)"} {"id": "ext.D2Common.D2COMMON_GetUnitOffsetX_D2COMMON_GetUnitOffset", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2Common", "author": "kidpaddle94 / Necrolis (Phrozen Keep t=62562)", "desc": "Supply the isometric screen-offset X/Y of a unit; consumed by the NON-perspective branch of both functions. | src: D2COMMON_GetUnitOffsetX(pUnit) ... D2COMMON_GetUnitOffsetY(pUnit)", "source": ["https://d2mods.info/forum/viewtopic.php?t=62562"], "locator": "D2Common exports (names only; no ordinals given)"} {"id": "ext.D2Common.D2COMMON_GetUnitPositionX_D2COMMON_GetUnitPosi", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2Common", "author": "kidpaddle94 / Necrolis (Phrozen Keep t=62562)", "desc": "Supply the world-space X/Y of a unit; consumed by the PERSPECTIVE branch (fed into D2GFX_AdjustPerspectivePosition). | src: int nX = D2COMMON_GetUnitPositionX(pUnit);\nint nY = D2COMMON_GetUnitPositionY(pUnit);", "source": ["https://d2mods.info/forum/viewtopic.php?t=62562"], "locator": "D2Common exports (names only; no ordinals given)"} {"id": "ext.D2Client.D2CLIENT_gnGlobalUiState", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2Client", "author": "kidpaddle94 / Necrolis (Phrozen Keep t=62562)", "desc": "Current UI panel state, switched on in the perspective branch. UISTATE_RIGHT => nAdjustX -= 256; UISTATE_LEFT => nAdjustX += 256. The 256 is the side-panel width shift applied when a left/right panel is open. | src: switch (*D2CLIENT_gnGlobalUiState) { case UISTATE_RIGHT: nAdjustX -= 256; case UISTATE_LEFT: nAdjustX += 256; }", "source": ["https://d2mods.info/forum/viewtopic.php?t=62562"], "locator": "D2Client global (dereferenced *D2CLIENT_gnGlobalUiState; no address given)"} {"id": "ext.D2Client.256px_panel_offset", "kind": "note", "status": "sourced", "trust": "trusted", "module": "D2Client", "author": "kidpaddle94 / Necrolis (Phrozen Keep t=62562)", "desc": "The 256-pixel horizontal correction: subtract 256 from adjusted X when the RIGHT panel is up, add 256 when the LEFT panel is up. Applied only in perspective mode (isometric offsets already bake in the shift via 6FBC9960/6FBCC418).", "source": ["https://d2mods.info/forum/viewtopic.php?t=62562"], "locator": "perspective branch, UISTATE switch", "value": "256"} {"id": "ext.D2Client.D2CLIENT_gnHoverX_D2CLIENT_gnHoverY", "kind": "global", "status": "sourced", "trust": "trusted", "module": "D2Client", "author": "kidpaddle94 / Necrolis (Phrozen Keep t=62562)", "desc": "Destination globals for the hover cursor/box position. Non-perspective: Y carries an extra -8 vs the draw formula. Perspective: Y carries an extra +16. | src: *D2CLIENT_gnHoverX = ...; *D2CLIENT_gnHoverY = nAdjustY + 16;", "source": ["https://d2mods.info/forum/viewtopic.php?t=62562"], "rva": "0xc0d30"} {"id": "ext.D2Client.UNITHOVER_Main_dwType_dispatch", "kind": "function", "status": "sourced", "trust": "trusted", "module": "D2Client", "author": "kidpaddle94 / Necrolis (Phrozen Keep t=62562)", "desc": "After computing hover coords, dispatches to per-type handlers: UNIT_PLAYER->UNITHOVER_PlayerUnits, UNIT_MONSTER->UNITHOVER_MonsterUnits, UNIT_OBJECT->UNITHOVER_ObjectUnits, UNIT_ITEM->UNITHOVER_ItemUnits, UNIT_TILE->UNITHOVER_TileUnits; default returns. | src: switch (pUnit->dwType) { case UNIT_PLAYER: UNITHOVER_PlayerUnits(pUnit); case UNIT_MONSTER: UNITHOVER_MonsterUnits(pUnit); case UNIT_OBJECT: UNITHOVER_ObjectUnits(pUnit); case UNIT", "source": ["https://d2mods.info/forum/viewtopic.php?t=62562"], "rva": "0xc0d30"} {"id": "ext.D2Client/D2Common.Necrolis_isometric_not_perspective_special_off", "kind": "note", "status": "sourced", "trust": "trusted", "module": "D2Client/D2Common", "author": "kidpaddle94 / Necrolis (Phrozen Keep t=62562)", "desc": "Correction/caveat on the render math: D2 default is ISOMETRIC projection; 'perspective' is a depth distortion applied only in D3D mode. Objects and missiles have special (file-derived, NOT image) coordinate offsets you must adjust for depending on where you read coords from; supporting perspective mode requires the 'order aware adjustment' for objects. | src: this is isometric projection, not perspective projection (which is a depth distortion you can apply in D3D mode)... objects and missiles have special offsets you need to adjust for", "source": ["https://d2mods.info/forum/viewtopic.php?t=62562"], "locator": "Post 3, Necrolis, Oct 31 2015"} {"id": "ext.GET_VERSION_D2Client", "kind": "function", "status": "sourced", "trust": "trusted", "module": "", "author": "Yohann Nicolas / PlugY (Speakus mirror)", "desc": "D2Client.dll version probe: DWORD at base+0x17F. Render-critical module (client-side draw/UI); its detected version selects the offset table used for all client render hacks. | src: GET_VERSION(D2Client,\t17F,\t00000000, 14500000, 12500000, 0D814800, 0D812800, 0DA01000, 0DA03000);", "source": ["https://raw.githubusercontent.com/Speakus/plugy/master/PlugY/D2wrapper.cpp"], "rva": "0x17f", "value": "shift=17F; 109b=00000000 109d=14500000 110=12500000 111=0D814800 111b=0D812800 112=0DA01000 113c=0DA03000"} {"id": "ext.GET_VERSION_D2gfx", "kind": "function", "status": "sourced", "trust": "trusted", "module": "", "author": "Yohann Nicolas / PlugY (Speakus mirror)", "desc": "D2gfx.dll (D2Gfx) version probe: DWORD at base+0x10D. Graphics/present module; version selects render offsets. Note col7 (V113c) sig is 00000000 (same literal as D2Client col1) — value copied verbatim as read. | src: GET_VERSION(D2gfx,\t10D,\tEB000000, 006FA700, 00000010, 2A000401, 19000401, 0B210E00, 00000000);", "source": ["https://raw.githubusercontent.com/Speakus/plugy/master/PlugY/D2wrapper.cpp"], "rva": "0x10d", "value": "shift=10D; 109b=EB000000 109d=006FA700 110=00000010 111=2A000401 111b=19000401 112=0B210E00 113c=00000000"} {"id": "ext.GET_VERSION_D2Win", "kind": "function", "status": "sourced", "trust": "trusted", "module": "", "author": "Yohann Nicolas / PlugY (Speakus mirror)", "desc": "D2Win.dll version probe: DWORD at base+0x1699. UI/window/panel module; version selects offsets used by the panel (new-interfaces / stash) render hacks. | src: GET_VERSION(D2Win,\t1699,\t88686F8C, 84686F8C, D094686F, F0030000, 001435E8, 8B088F44, 0013F5E8);", "source": ["https://raw.githubusercontent.com/Speakus/plugy/master/PlugY/D2wrapper.cpp"], "rva": "0x1699", "value": "shift=1699; 109b=88686F8C 109d=84686F8C 110=D094686F 111=F0030000 111b=001435E8 112=8B088F44 113c=0013F5E8"} {"id": "ext.Install_NewInterfaces_entry_point_call_site", "kind": "function", "status": "sourced", "trust": "trusted", "module": "", "author": "Yohann Nicolas / PlugY (Speakus mirror)", "desc": "Panel installer entry point: the new-interfaces (large stash / shared-stash panels + reworked inventory UI) hooks are installed only when the active_newInterfaces config flag is set. The Install_NewInterfaces() DEFINITION is NOT in D2wrapper.cpp (it lives in the interface/panel source, referenced via #include); D2wrapper.cpp holds only the gated call site. | src: if (active_newInterfaces) Install_NewInterfaces();", "source": ["https://raw.githubusercontent.com/Speakus/plugy/master/PlugY/D2wrapper.cpp"], "locator": "D2wrapper.cpp, active_newInterfaces gate", "value": "if (active_newInterfaces) Install_NewInterfaces();"} {"id": "ext.Install_MultiPageStash_entry_point_call_site", "kind": "function", "status": "sourced", "trust": "trusted", "module": "", "author": "Yohann Nicolas / PlugY (Speakus mirror)", "desc": "Panel installer entry point: the multi-page (paged) stash hooks are installed only when active_multiPageStash is set. Definition not in D2wrapper.cpp (external source via #include); D2wrapper.cpp holds only the gated call site. | src: if (active_multiPageStash) Install_MultiPageStash();", "source": ["https://raw.githubusercontent.com/Speakus/plugy/master/PlugY/D2wrapper.cpp"], "locator": "D2wrapper.cpp, active_multiPageStash gate", "value": "if (active_multiPageStash) Install_MultiPageStash();"} {"id": "ext.113c ADDRESSES.env_effects", "kind": "global", "status": "sourced", "trust": "trusted", "module": "1.13c ADDRESSES", "author": "Necrolis (d2-rs)", "desc": "environment effects global (weather/env array)", "source": ["https://github.com/Necrolis/d2-rs"], "rva": "0x11bf60", "value": "0x11bf60"} {"id": "ext.113c ADDRESSES.entity_table", "kind": "global", "status": "sourced", "trust": "trusted", "module": "1.13c ADDRESSES", "author": "Necrolis (d2-rs)", "desc": "primary entity table", "source": ["https://github.com/Necrolis/d2-rs"], "rva": "0x10a608", "value": "0x10a608"} {"id": "ext.113c ADDRESSES.entity_table2", "kind": "global", "status": "sourced", "trust": "trusted", "module": "1.13c ADDRESSES", "author": "Necrolis (d2-rs)", "desc": "secondary entity table", "source": ["https://github.com/Necrolis/d2-rs"], "rva": "0x109a08", "value": "0x109a08"} {"id": "ext.113c ADDRESSES.client_loop_globals", "kind": "global", "status": "sourced", "trust": "trusted", "module": "1.13c ADDRESSES", "author": "Necrolis (d2-rs)", "desc": "client loop globals block", "source": ["https://github.com/Necrolis/d2-rs"], "rva": "0x1197e0", "value": "0x1197e0"} {"id": "ext.113c ADDRESSES.apply_pos_change", "kind": "function", "status": "sourced", "trust": "trusted", "module": "1.13c ADDRESSES", "author": "Necrolis (d2-rs)", "desc": "Applies a DyPos position change. Signature per comment: __stdcall(DyPos* @ esi, FixedU16, FixedU16, Room*). DyPos pointer passed in ESI (register/thiscall-ish stdcall). | src: // Signature: `__stdcall(DyPos* @ esi, FixedU16, FixedU16, Room*)`\n apply_pos_change: 0xda40,", "source": ["https://github.com/Necrolis/d2-rs"], "rva": "0xda40", "value": "0xda40"} {"id": "ext.113c ADDRESSES.in_perspective", "kind": "function", "status": "sourced", "trust": "trusted", "module": "1.13c ADDRESSES", "author": "Necrolis (d2-rs)", "desc": "perspective-mode check (draw/render path)", "source": ["https://github.com/Necrolis/d2-rs"], "locator": "ord 10013", "value": "Ordinal(10013)"} {"id": "ext.113c ADDRESSES.hwnd", "kind": "function", "status": "sourced", "trust": "trusted", "module": "1.13c ADDRESSES", "author": "Necrolis (d2-rs)", "desc": "main window handle accessor", "source": ["https://github.com/Necrolis/d2-rs"], "locator": "ord 10048", "value": "Ordinal(10048)"} {"id": "ext.113c ADDRESSES.draw_menu", "kind": "function", "status": "sourced", "trust": "trusted", "module": "1.13c ADDRESSES", "author": "Necrolis (d2-rs)", "desc": "draw menu function", "source": ["https://github.com/Necrolis/d2-rs"], "locator": "ord 10024", "value": "Ordinal(10024)"} {"id": "ext.113c ADDRESSES.cursor_table", "kind": "global", "status": "sourced", "trust": "trusted", "module": "1.13c ADDRESSES", "author": "Necrolis (d2-rs)", "desc": "cursor table", "source": ["https://github.com/Necrolis/d2-rs"], "rva": "0xd8558", "value": "0xd8558"} {"id": "ext.113c ADDRESSES.game_cursor", "kind": "global", "status": "sourced", "trust": "trusted", "module": "1.13c ADDRESSES", "author": "Necrolis (d2-rs)", "desc": "game cursor global", "source": ["https://github.com/Necrolis/d2-rs"], "rva": "0xfb834", "value": "0xfb834"} {"id": "ext.113c ADDRESSES.summit_cloud_x_pos", "kind": "global", "status": "sourced", "trust": "trusted", "module": "1.13c ADDRESSES", "author": "Necrolis (d2-rs)", "desc": "summit cloud X position (0 = not present/unused in 1.13c)", "source": ["https://github.com/Necrolis/d2-rs"], "locator": "0", "value": "0"} {"id": "ext.113c ADDRESSES.draw_line", "kind": "function", "status": "sourced", "trust": "trusted", "module": "1.13c ADDRESSES", "author": "Necrolis (d2-rs)", "desc": "draw line primitive", "source": ["https://github.com/Necrolis/d2-rs"], "locator": "ord 10010", "value": "Ordinal(10010)"} {"id": "ext.113c ADDRESSES.find_closest_color", "kind": "function", "status": "sourced", "trust": "trusted", "module": "1.13c ADDRESSES", "author": "Necrolis (d2-rs)", "desc": "palette find-closest-color", "source": ["https://github.com/Necrolis/d2-rs"], "locator": "ord 10190", "value": "Ordinal(10190)"} {"id": "ext.113c ADDRESSES.viewport_width", "kind": "global", "status": "sourced", "trust": "trusted", "module": "1.13c ADDRESSES", "author": "Necrolis (d2-rs)", "desc": "viewport width global", "source": ["https://github.com/Necrolis/d2-rs"], "rva": "0xf9e14", "value": "0xf9e14"} {"id": "ext.113c ADDRESSES.viewport_height", "kind": "global", "status": "sourced", "trust": "trusted", "module": "1.13c ADDRESSES", "author": "Necrolis (d2-rs)", "desc": "viewport height global (immediately after width, +4)", "source": ["https://github.com/Necrolis/d2-rs"], "rva": "0xf9e18", "value": "0xf9e18"} {"id": "ext.113c ADDRESSES.viewport_shift", "kind": "global", "status": "sourced", "trust": "trusted", "module": "1.13c ADDRESSES", "author": "Necrolis (d2-rs)", "desc": "viewport shift global (the render offset knob)", "source": ["https://github.com/Necrolis/d2-rs"], "rva": "0x11c418", "value": "0x11c418"} {"id": "ext.113c ADDRESSES.max_weather_particles", "kind": "global", "status": "sourced", "trust": "trusted", "module": "1.13c ADDRESSES", "author": "Necrolis (d2-rs)", "desc": "max weather particles", "source": ["https://github.com/Necrolis/d2-rs"], "rva": "0x113934", "value": "0x113934"} {"id": "ext.113c ADDRESSES.weather_angle", "kind": "global", "status": "sourced", "trust": "trusted", "module": "1.13c ADDRESSES", "author": "Necrolis (d2-rs)", "desc": "weather angle", "source": ["https://github.com/Necrolis/d2-rs"], "rva": "0x113918", "value": "0x113918"} {"id": "ext.113c ADDRESSES.rain_speed", "kind": "global", "status": "sourced", "trust": "trusted", "module": "1.13c ADDRESSES", "author": "Necrolis (d2-rs)", "desc": "rain speed", "source": ["https://github.com/Necrolis/d2-rs"], "rva": "0x1138f4", "value": "0x1138f4"} {"id": "ext.113c ADDRESSES.is_snowing", "kind": "global", "status": "sourced", "trust": "trusted", "module": "1.13c ADDRESSES", "author": "Necrolis (d2-rs)", "desc": "is-snowing flag", "source": ["https://github.com/Necrolis/d2-rs"], "rva": "0x11bf78", "value": "0x11bf78"} {"id": "ext.113c ADDRESSES.sine_table", "kind": "global", "status": "sourced", "trust": "trusted", "module": "1.13c ADDRESSES", "author": "Necrolis (d2-rs)", "desc": "sine lookup table", "source": ["https://github.com/Necrolis/d2-rs"], "rva": "0x2f470", "value": "0x2f470"} {"id": "ext.113c ADDRESSES.gen_weather_particle", "kind": "function", "status": "sourced", "trust": "trusted", "module": "1.13c ADDRESSES", "author": "Necrolis (d2-rs)", "desc": "generate one weather particle. Signature: stdcall(&mut Rng). | src: // Signature: stdcall(&mut Rng)\n gen_weather_particle: 0x80700,", "source": ["https://github.com/Necrolis/d2-rs"], "rva": "0x80700", "value": "0x80700"} {"id": "ext.113c ADDRESSES.env_array_remove", "kind": "function", "status": "sourced", "trust": "trusted", "module": "1.13c ADDRESSES", "author": "Necrolis (d2-rs)", "desc": "remove entry from environment array", "source": ["https://github.com/Necrolis/d2-rs"], "locator": "ord 10065", "value": "Ordinal(10065)"} {"id": "ext.BaseAddresses (from v111a, re-exported through v112 into v113c).BASE_ADDRESSES_client", "kind": "global", "status": "sourced", "trust": "trusted", "module": "BaseAddresses (from v111a, re-exported through v112 into v113c)", "author": "Necrolis (d2-rs)", "desc": "D2Client.dll default image base", "source": ["https://github.com/Necrolis/d2-rs"], "rva": "0x6fab0000", "value": "0x6fab0000"} {"id": "ext.BaseAddresses.BASE_ADDRESSES_game", "kind": "global", "status": "sourced", "trust": "trusted", "module": "BaseAddresses", "author": "Necrolis (d2-rs)", "desc": "D2Game.dll default image base", "source": ["https://github.com/Necrolis/d2-rs"], "rva": "0x6fc20000", "value": "0x6fc20000"} {"id": "ext.BaseAddresses.BASE_ADDRESSES_gfx", "kind": "global", "status": "sourced", "trust": "trusted", "module": "BaseAddresses", "author": "Necrolis (d2-rs)", "desc": "D2gfx.dll default image base (the module whose ordinals draw_menu/draw_line/in_perspective/find_closest_color/hwnd/env_array_remove are exports of)", "source": ["https://github.com/Necrolis/d2-rs"], "rva": "0x6fa80000", "value": "0x6fa80000"} {"id": "ext.BaseAddresses.BASE_ADDRESSES_win", "kind": "global", "status": "sourced", "trust": "trusted", "module": "BaseAddresses", "author": "Necrolis (d2-rs)", "desc": "D2Win.dll default image base", "source": ["https://github.com/Necrolis/d2-rs"], "rva": "0x6f8e0000", "value": "0x6f8e0000"} {"id": "struct.DyPos", "kind": "struct", "status": "sourced", "trust": "trusted", "module": "d2interface", "author": "Necrolis (d2-rs)", "desc": "Dynamic (moving) entity position. #[repr(C)]. Fields in order: linear_pos: LinearM2d; iso_pos: IsoP2d; target_pos: [LinearM2d; 3]; room: Option>; _padding1: [u32;4]; entity: NonNull. This is the struct apply_pos_change mutates (ptr in ESI). | src: #[repr(C)] pub struct DyPos { pub linear_pos: LinearM2d, pub iso_pos: IsoP2d, pub target_pos: [LinearM2d; 3], pub room: Option>, pub _padding1: [u32; ", "source": ["https://github.com/Necrolis/d2-rs"], "locator": "defined v109d, re-exported to v113c"} {"id": "struct.StaticPos", "kind": "struct", "status": "sourced", "trust": "trusted", "module": "d2interface", "author": "Necrolis (d2-rs)", "desc": "Static (non-moving) entity position. #[repr(C)]. Fields: room: Option>; iso_pos: IsoP2d; linear_pos: LinearM2d; _padding1: [u32;3]. | src: #[repr(C)] pub struct StaticPos { pub room: Option>, pub iso_pos: IsoP2d, pub linear_pos: LinearM2d, pub _padding1: [u32; 3], }", "source": ["https://github.com/Necrolis/d2-rs"], "locator": "defined v109d"} {"id": "struct.EntityPos", "kind": "struct", "status": "sourced", "trust": "trusted", "module": "d2interface", "author": "Necrolis (d2-rs)", "desc": "#[repr(C)] union: s: Option> | d: Option>. Which arm is valid depends on Entity.kind. | src: #[repr(C)] pub union EntityPos { pub s: Option>, pub d: Option>, }", "source": ["https://github.com/Necrolis/d2-rs"], "locator": "defined v109d"} {"id": "struct.Entity", "kind": "struct", "status": "sourced", "trust": "trusted", "module": "d2interface", "author": "Necrolis (d2-rs)", "desc": "#[repr(C)]. Render-relevant fields: kind: EntityKind; class_id:u32; mem_pool; id:u32; state:u32; data; act_id:u32; dungeon; rng:Rng; seed:u32; pos: EntityPos; anim_frame_def; seq_frame_count:FU8; seq_frame:FU8; seq_anim_rate:FU8; anim_state:u32; frame:FU8; frame_count:FU8; anim_rate:u16; frame_event:u8; anim_data; gfx_info; _padding0:[u32;1]; stats; inv; light; light_width:u32; _padding1:[u32;30]; next_entity: Option>; next_in_room: Option>; _p | src: pub kind: EntityKind, pub class_id: u32, ... pub pos: EntityPos, pub anim_frame_def: *mut (), pub seq_frame_count: FU8, pub seq_frame: FU8, pub seq_anim_rate: FU8, pub anim_state: ", "source": ["https://github.com/Necrolis/d2-rs"], "locator": "defined v109d"} {"id": "struct.Room", "kind": "struct", "status": "sourced", "trust": "trusted", "module": "d2interface", "author": "Necrolis (d2-rs)", "desc": "#[repr(C)]. connected: Option>>; _padding1:[u32;3]; data:u32; _padding2:[u32;4]; connected_count:u32; _padding3:[u32;9]; pos: LinearM2d; size: M2d; _padding4:[u32;9]. pos/size are the room world placement used to resolve iso/linear coords. | src: #[repr(C)] pub struct Room { pub connected: Option>>, pub _padding1: [u32; 3], pub data: u32, pub _padding2: [u32; 4], pub connected_count: u32, pub _padding3", "source": ["https://github.com/Necrolis/d2-rs"], "locator": "defined v109d"} {"id": "struct.BaseAddresses", "kind": "struct", "status": "sourced", "trust": "trusted", "module": "d2interface", "author": "Necrolis (d2-rs)", "desc": "pub struct BaseAddresses { pub client: usize, pub common: usize, pub fog: usize, pub game: usize, pub gfx: usize, pub win: usize } | src: pub struct BaseAddresses { pub client: usize, pub common: usize, pub fog: usize, pub game: usize, pub gfx: usize, pub win: usize, }", "source": ["https://github.com/Necrolis/d2-rs"], "locator": "module.rs"} {"id": "finding.screenshiftx_is_floor_shift", "kind": "finding", "status": "testing", "trust": "trusted", "author": "The Esoteric Path (SGD2FreeRes + mir + planqi ingest 2026-07-18)", "desc": "BREAKTHROUGH: the -320 FLOOR/ROOF shift source is ScreenShiftX = D2Client+0x11B9A0 (mir names it 'ScreenShiftX'; planqi names 0x11B9A0 'PanelOffsetX -- horizontal shift applied when side panels are open'). SGD2FreeRes REPLACES vanilla SetScreenShift with Sgd2fr_D2Client_SetScreenShift (set_screen_shift/replacement.cpp L54-63; hook D2Client+0xC39F6 in 1.13c, found via write-BP on ScreenShiftX/Y): screen_shift_x = display_width/2 - 640/2 => at 1280 wide = 640-320 = the centering shift. The floor/tile projection reads ScreenShiftX. Our no-shift lens zeroed offX (GeneralPlayAreaCameraShiftX 0x11C418) + ctx draw_left -- fixing WALLS+UNITS -- but NEVER touched 0x11B9A0, so FLOOR/ROOF stayed shifted. That is the exact residual. NEXT: author 0x11B9A0=0 each frame alongside offX (or neutralize the SetScreenShift hook @0xC39F6); x32dbg live-read of 0x11B9A0 panel-open expects the -320-class value.", "source": ["https://github.com/mir-diablo-ii-tools/SlashGaming-Diablo-II-Free-Resolution", "https://github.com/mir-diablo-ii-tools/Diablo-II-Address-Table/blob/master/1.13C.txt", "https://github.com/planqi/slashdiablo-maphack"], "refs": ["finding.floor_shift_ledger", "finding.survey_floor_is_downstream", "reframe.d2dx_no_per_category_transform"]} {"id": "reframe.d2dx_no_per_category_transform", "kind": "finding", "status": "confirmed", "trust": "trusted", "author": "The Esoteric Path (bolrog + Necrolis/d2dx-annihilus source read 2026-07-18)", "desc": "OVERTURNS finding.survey_floor_is_downstream. Full source read of D2DX (bolrog + Necrolis fork): D2DX applies NO per-category floor-vs-wall positional transform -- TextureCategory::Floor(4)/Wall(6) are never used to offset geometry (GameHelper::RefineTextureCategoryFromGameAddress only TAGS batches for AA). The ONLY post-capture world shift is UnitMotionPrediction (D2DXContext.cpp OnBufferSwap ~408-436): UNIFORM across all world geometry (floor AND wall), skipped only for surfaceId==USER_INTERFACE(16383). We already set nomotionprediction=true -> no change. RenderContext::UpdateViewport sets ONE uniform viewport+scissor; Constants CB carries only screenSize/invScreenSize, no translate. => the -320 floor shift is NOT downstream in D2DX; it is upstream (ScreenShiftX). The survey's dMinX 'downstream' read was an artifact of the confounded aggregate + not having neutralized 0x11B9A0.", "source": ["https://github.com/bolrog/d2dx", "https://github.com/Necrolis/d2dx-annihilus"], "refs": ["finding.survey_floor_is_downstream", "finding.screenshiftx_is_floor_shift"]} {"id": "finding.sgd2freeres_deadzone_architecture", "kind": "finding", "status": "confirmed", "trust": "trusted", "author": "The Esoteric Path (SGD2FreeRes source read 2026-07-18)", "desc": "The panel/dead-zone architecture SGD2FreeRes imposes (clean-room from its develop-branch source): (1) SetGeneralDisplayWidthAndHeight -> GeneralDisplayWidth/Height (0xDBC48/4C). (2) SetScreenShift (hook D2Client+0xC39F6) -> ScreenShiftX/Y (0x11B9A0/4) centering = the -320 floor shift. (3) SetTileCullingBound (hook D2Client+0x8A4D0; CullingSpec{flags@0x0, draw_window_rect RECT@0x4}) -> tile draw + cull windows. (4) DrawLeft/RightScreenBackground (hook D2Client+0xC3AA6) -> paints the BLACK dead-zone: d2gfx::DrawRectangle(0,0,width/2,height) 'to stop transparent-DC6 cheaters' + tiles 800BorderFrame around the 640 play area; stock bg draws NOP'd at +0x271ED / +0x270F1. => black perimeter = DrawScreenBackground; floor shift = SetScreenShift. To reveal the world behind the panel: neutralize DrawScreenBackground and zero ScreenShiftX.", "source": ["https://github.com/mir-diablo-ii-tools/SlashGaming-Diablo-II-Free-Resolution"], "refs": ["finding.screenshiftx_is_floor_shift", "finding.clip_is_d2dx_drop_confirmed", "OQ.d2dx_retag_black"]} {"id": "finding.novelty_audit_2026_07_18", "kind": "reference", "status": "noted", "trust": "verified", "author": "The Esoteric Path (novelty audit 2026-07-18)", "desc": "NOVELTY vs public prior art (10 findings audited): 8 NOVEL (no public source states the technique/conclusion): the DrawGame 1.13c pipeline map; offX single-write@0x6FB5AF7C read-173x; the no-panel view-state lens; the floor-un-shifted-at-seam experiment; the worldCtx(0x11C3C4) menu gate; playAreaW-governs-floor-AND-hittest; the whole dead-zone-fill endeavor; the render-context struct at *(0x11C3C4). 2 CORROBORATED (attribute, do not claim as discovery): (a) D2DXWiden = bolrog's SANCTIONED public Configurator API SetCustomResolution -- attribute bolrog; (b) GlideUnclamp is adjacent to IAmTrial's documented hardcoded-640 D2Glide clamp @+0x15A68 (a DIFFERENT site than our 0x6F856840 cull -- ours is distinct). SUBSTRATE (named globals ScreenShiftX 0x11B9A0, GeneralPlayAreaCameraShiftX 0x11C418, GeneralDisplayWidth 0xDBC48) is PUBLIC (mir) -- attribute; the behavioral CONCLUSIONS + techniques on top are ours. Attribution: mir, bolrog, IAmTrial, Necrolis, kidpaddle94/JayTee.", "source": ["https://github.com/mir-diablo-ii-tools/Diablo-II-Address-Table", "https://github.com/bolrog/d2dx"], "refs": ["finding.screenshiftx_is_floor_shift", "reframe.d2dx_no_per_category_transform"]} {"id": "finding.live_rpm_2026_07_18", "kind": "finding", "status": "confirmed", "trust": "verified", "author": "The Esoteric Path (live elevated RPM/WPM session 2026-07-18 on running Game.exe)", "desc": "LIVE against the running 1.13c binary (esoteric.dll mod ON), via elevated ReadProcessMemory/WriteProcessMemory. (1) worldCtx (D2Client+0x11C3C4) CONFIRMED null@menu, non-null in-game (0x214739D4) -> verifies finding.menu_worldctx_gate vs the binary. (2) FALSIFIES finding.screenshiftx_is_floor_shift: ScreenShiftX (0x11B9A0) = +320 CONSTANT in-game (SGD2FreeRes centering, re-written per-frame), identical in mode 0/1/2; a live freeze of 0x11B9A0=0 did NOT move the floor (only a border element flickered) -> the FLOOR does NOT read ScreenShiftX. (3) PANEL-DELTA SCAN (12 globals + render-ctx struct fields, panel-closed vs inventory vs character): opening a panel changes NO horizontal shift global -- ScreenShiftX, offX(0x11C418; our lens holds 0), OffsetPtX(0x11C1F8=0), ctxL(0), ctxR(1280), playAreaW(0xF9E14=1280) ALL constant across mode 0/1/2. Only ctxScrollX(=global 0x119960) and mouse offsets vary, and that is CAMERA MOVEMENT (character walking), not the panel. (4) CONCLUSION: the floor residual shift is STATIC (matches Doug: 'always shifted, not sliding') and is driven by NO authorable global on panel-open -> it is INTERNAL to the floor pass (PASS1 / FloorFlush 0x9ED50), a constant floor-vs-wall X-base difference. Re-confirms finding.floor_shift_internal_to_pass1; global-poke approach exhausted. NEXT: x32dbg breakpoint inside FloorFlush 0x9ED50 with a panel open -> read the X base the floor computes and compare to the wall pass (PASS2 0x8B110). RPM cannot observe internal computed values.", "source": ["live: RPM/WPM on Game.exe PID 17412, D2Client.dll base 0x6FAB0000, mod ON"], "refs": ["finding.screenshiftx_is_floor_shift", "finding.floor_shift_internal_to_pass1", "finding.menu_worldctx_gate", "reframe.d2dx_no_per_category_transform"]} {"id": "corpus.DrawFramedTextExt", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Mnw1995 (phrozen_code Discord)", "module": "D2Win", "desc": "Draws framed text: (wchar_t* text, int nX, int nY, int nTextColor, int nAlign, int nRectColor). UI text-render primitive. | D2FUNC(D2WIN, DrawFramedTextExt, void, __fastcall, (wchar_t *wszText, int nX, int nY, int nTextColor, int nAlign, int nRectColor), 0xACD0) //D2Win.#10", "source": ["discord:phrozen_code msg 323590369210269698"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Win.#10130 / ordinal 0xACD0"} {"id": "corpus.Unit_Display_globals", "kind": "global", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Two D2Client globals referenced in the Unit_Display function; 6FBBA4A0 is believed to be the monster description string (resists, montype, etc.) built for the hover panel. | I have a feeling its used to build 6FBBA4A0, which is the monster desc string (resists, montype etc)", "source": ["discord:phrozen_code msg 323589603221307394"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FBB9FE0, 6FBBA4A0"} {"id": "corpus.D2CreatePL2", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2CMP", "desc": "Builds a PL2 (palette+shift-tables) from a 256-color palette; entry point for changing D2's color scheme. D2PL2Strc* __stdcall D2CreatePL2(BYTE pPalette[256]). | D2CMP.#10000 D2PL2Strc* __stdcall D2CreatePL2(BYTE pPalette[256])", "source": ["discord:phrozen_code msg 327795217996578818"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2CMP.#10000"} {"id": "corpus.UNITDRAW_DrawOutline", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Draws the selection/aura outline around a unit. BOOL __fastcall UNITDRAW_DrawOutline(D2UnitStrc* pUnit). Part of the client unit-render path. | Function: UNITDRAW_DrawOutline Address: D2Client.0x6FB59F20", "source": ["discord:phrozen_code msg 338852972924633088"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FB59F20"} {"id": "corpus.UNITDRAW_TickOutline", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Decrements a unit's outline tick and returns whether to draw it (unless STATE_ATTACHED). Reads pUnit->dwOutlineTick. Part of unit-render tick. | Function: UNITDRAW_TickOutline Address: D2Client.0x6FB29A40 ... DWORD dwTick = pUnit->dwOutlineTick;", "source": ["discord:phrozen_code msg 338853254375145472"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FB29A40"} {"id": "corpus.Unit_visibility_check_is_unit_shown", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Under 1.10 determines whether a unit is drawn/shown; forcing its dead-check to return false keeps dead units visible. A gate in the client draw path. | D2Client.0x6FACE8F0 under 1.10 determines if a unit is shown", "source": ["discord:phrozen_code msg 345494641593810945"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FACE8F0"} {"id": "corpus.Life_orb_draw", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Mnw1995 (phrozen_code Discord)", "module": "D2Client", "desc": "Draws the (life/mana) orb on the HUD panel. Direct panel/HUD render entry. | D2Client.0x6FAFF9D0 draws the orb", "source": ["discord:phrozen_code msg 347831089336811520"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FAFF9D0"} {"id": "corpus.D2AddRoomToDrawList_D2IterateRooms", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client / D2Common", "desc": "The room draw-list build step: D2Client passes its D2AddRoomToDrawList callback to D2IterateRooms (D2Common #10049) to walk visible rooms and enqueue them for drawing. Core of the world/floor render pipeline. | PUSH ... CALL ; JMP to D2Common.#10049", "source": ["discord:phrozen_code msg 350328579759800321"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.D2AddRoomToDrawList (pushed at 6FAB827B); D2IterateRooms = JMP to D2Common.#10049"} {"id": "corpus.COLLISION_CheckMask", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Common", "desc": "Reads the per-subtile collision mask for a room coord: indexes pRoom->pCollisionGrid->pCollisionMask via ((y - subtilesTop)*subtilesWidth - subtilesLeft + x) & fMask. Reveals D2RoomCollisionStrc layout (pCollisionMask, pCoords with dwSubtilesTop/Left/Width). Governs floor/tile walkability that render+pathing share. | WORD __fastcall COLLISION_CheckMask(DRLGRoom* pRoom, int nXpos, int nYpos, WORD fMask) ... pMask[(((nYpos - pCoords->dwSubtilesTop) * pCoords->dwSubti", "source": ["discord:phrozen_code msg 350631905181564929"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Common.#10118"} {"id": "struct.COLLIDE_tile_collision_flags", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Common", "desc": "Full per-subtile collision bitmask enum. Notably COLLIDE_BLOCK_PLAYER 0x0001 = 'black space' in Arcane Sanctuary / cliff walls (the void/dead-zone tiles); COLLIDE_ALTERNATE_FLOOR 0x0010 (some floors set it); COLLIDE_BLANK 0x0020 returned for invalid subtile; COLLIDE_WALL 0x0004. Directly relevant to floor/void rendering behavior. | COLLIDE_BLOCK_PLAYER = 0x0001, // 'black space' in arcane sanctuary, cliff walls etc ... COLLIDE_ALTERNATE_FLOOR = 0x0010 ... COLLIDE_BLANK = 0x0020, ", "source": ["discord:phrozen_code msg 350632827831713812"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "bitmask 0x0001..0x8000"} {"id": "struct.D2Renderer_function_table_OpenD2_reimpl", "kind": "struct", "status": "sourced", "trust": "sourced", "author": "eezstreet (cla$$ics) (phrozen_code Discord)", "module": "OpenD2", "desc": "Reverse-engineer's abstracted renderer interface mirroring D2's draw model: RF_Init/Shutdown/Present, RF_RegisterTexture, RF_SetTexturePixels(tex,pixels,nPalette), RF_DrawTexture(tex,x,y,w,h,u,v). Notes a TODO for palshifted-cel drawing. Useful mental model of the D2 blit pipeline. | struct D2Renderer{ void (*RF_Present)(); ... void (*RF_DrawTexture)(tex_handle texture, DWORD x, DWORD y, DWORD w, DWORD h, DWORD u, DWORD v); // TODO", "source": ["discord:phrozen_code msg 351914188660146176"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "n/a (eezstreet OpenD2 reimplementation, not stock)"} {"id": "struct.DC6_frame_decode_DC6_LoadImage", "kind": "struct", "status": "sourced", "trust": "sourced", "author": "eezstreet (cla$$ics) (phrozen_code Discord)", "module": "D2CMP", "desc": "DC6 image load layout: frames indexed dir*dwFrames+frame, each DC6Frame has dwWidth/dwHeight and dwNextBlock set to running pixel offset; the file offset/pointer table lives outside the dc6 body. Relevant to cel/graphics decoding. | memcpy(&pImage->pFrames[dwFramePos], gpDecodeBuffer + pFramePointers[dwFramePos], sizeof(DC6Frame)); pImage->pFrames[dwFramePos].dwNextBlock = dwTotal", "source": ["discord:phrozen_code msg 352896096907034625"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "DC6Frame; pImage->pFrames[dir*dwFrames+frame]"} {"id": "corpus.Gouraud_view_render_setup_D2CreateView_D2Bui", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Client-side view/render init trio: D2CreateView (called at 6FAA9501), D2BuildGouraudTables (6FAAB3C7), D2FreeGuaraudTables (6FAABB40). Gouraud tables drive the lighting/shading of the play-area render. | CALL D2Client.6FAB6FF0 ; D2CreateView() ... CALL D2Client.6FAB6AC0 ; D2BuildGouraudTables() ... CALL D2Client.6FAB6EB0 ; D2FreeGuaraudTables()", "source": ["discord:phrozen_code msg 362519549213671427"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.6FAB6FF0 D2CreateView; 6FAB6AC0 D2BuildGouraudTables; 6FAB6EB0 D2FreeGouraudTables"} {"id": "corpus.Charm_inventory_grid_function_1_13c", "kind": "global", "status": "sourced", "trust": "sourced", "author": "Thaison (phrozen_code Discord)", "module": "D2Common", "desc": "Function responsible for the charm inventory in 1.13c. Thaison supplies a CharmZone hook checking item grid position: pInventory at [EAX+0x2C], leftBorder/rightBorder at [+0x0C], top/bottomBorder at [+0x10] (top>=4, bottom<=8) to define the charm grid zone. Panel/inventory-grid render logic. | D2Common.dll - 0x28846 ... CMP DWORD PTR DS:[EAX+0x0C], 0 //leftBorder ... CMP DWORD PTR DS:[EAX+0x10], 4 //topBorder", "source": ["discord:phrozen_code msg 366181995681808384"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Common.dll 0x28846"} {"id": "corpus.PATH_NormalizeCoords", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Common", "desc": "Normalizes an X/Y coord pair (in place). __forceinline void __fastcall PATH_NormalizeCoords(int* pXpos, int* pYpos). Coordinate transform used in pathing/positioning. | Function: PATH_NormalizeCoords Address: D2Common.#10111", "source": ["discord:phrozen_code msg 371058499985342468"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Common.#10111"} {"id": "corpus.World_offset_panel_adjust_perspective_coord_", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "THE core screen-space transform for drawing a unit into the play area. Takes unit world X/Y, adds GFX position (Z folded into Y), then SUBTRACTS UNITDRAW_GetWorldXOffset()/YOffset() (the camera/scroll offset), and IF perspective on, ADDS UNITDRAW_GetPanelAdjust() and runs D2AdjustPerspectiveCoords. This is exactly the screen-shift / panel-offset math behind the play-area vs side-panel positioning. | nXpos -= UNITDRAW_GetWorldXOffset(); nYpos -= UNITDRAW_GetWorldYOffset(); if(GFXUTIL_CheckPerspective()){ nXpos += UNITDRAW_GetPanelAdjust(); D2Adjust", "source": ["discord:phrozen_code msg 371070877950803999"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "UNITDRAW_GetWorldXOffset / UNITDRAW_GetWorldYOffset / UNITDRAW_GetPanelAdjust / D2AdjustPerspectiveCoords / GFXUTIL_CheckPerspective; UNITDRAW_GetGFXPosition(pUnit,GFX_DRAW)"} {"id": "corpus.UNITDRAW_DrawOverlays", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Draws a unit's overlays; repeats the same world-offset/panel-adjust/perspective transform (subtract WorldX/YOffset, else-branch; or D2AdjustPerspectiveCoords + GetPanelAdjust + 16 in perspective). Second confirmed site of the panel-adjust screen-shift logic. void __fastcall(pUnit, dwColorTint, bBack, nXpos, nYpos, bPerspectiveDisabled). | Function: UNITDRAW_DrawOverlays Address: D2Client.0x6FB5A490 ... nXpos += UNITDRAW_GetPanelAdjust(); nXpos += 16; ... nXpos = pCoord.nXpos - UNITDRAW", "source": ["discord:phrozen_code msg 371071343413952512"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FB5A490"} {"id": "corpus.Collision_override_for_pass_through_units", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Common", "desc": "To let a unit/missile pass where it normally collides, find the flag the collision fns test and override it with an unused tile flag; likely a D2Common ordinal (points to COLLISION_CheckMask and the COLLIDE_* mask set). | you basically need to look what the fn's use to determine if they collide and override it with an unused tile flag; its likely a D2Common ordinal", "source": ["discord:phrozen_code msg 350630384083664896"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "COLLISION_CheckMask (#10118) + tile flags"} {"id": "struct.Control_D2Win_UI_control", "kind": "struct", "status": "sourced", "trust": "sourced", "author": "Mnw1995 (phrozen_code Discord)", "module": "D2Win", "desc": "D2Win UI control struct: dwType +0x00, pCellFile +0x04, dwDisabled +0x08, pos X/Y +0x0C/0x10, size X/Y +0x14/0x18, Initialize fn +0x1C, CallFunc (button) +0x28, CallBackFunc +0x34, pNext +0x3C, dwMaxLength/ButtonFlag +0x44, pFirstText/dwScrollEntries +0x48, pLastText/dwScrollPosition +0x4C, pSelectedText +0x50, wText[0x1A] +0x5C, pChildControl +0x90 | struct Control { DWORD dwType; //0x00 ... Control* pChildControl; //0x90 };", "source": ["discord:phrozen_code msg 378911653263048726"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "+0x00..+0x90"} {"id": "corpus.Merchant_store_panel_draw_D2Client", "kind": "note", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2Client", "desc": "Store panel draw path: when sgnInventoryMode in [INVMODE_TRADE..INVMODE_09], checks globals D2CLIENT_6FBCBC4C (tick gate), 6FBCBC54, 6FBCBC30, gdwActiveNpcGUID, gnInvPage, then calls STOREINVENTORYSCREEN_Main. 6FB3F710 is the key sub (likely click-spam/latency guard) | It's the part that draws the merchant store panel ... STOREINVENTORYSCREEN_Main();", "source": ["discord:phrozen_code msg 381887503935733761"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2CLIENT_6FB3F710, D2CLIENT_6FB3D300, STOREINVENTORYSCREEN_Main"} {"id": "corpus.Store_panel_draw_1_10_equiv", "kind": "note", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2Client", "desc": "1.10 equivalent of store-panel draw: iterates D2CLIENT_dword_6FBB37AC..37FC stepping 20 bytes, sets gnInventoryMode=VENDORMODE_TRADE, calls 6FB575B0 with cursor item | *D2CLIENT_gnInventoryMode = VENDORMODE_TRADE;", "source": ["discord:phrozen_code msg 381891883716313099"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2CLIENT_6FAE8F90, dword_6FBB5904/590C/58E8/37AC"} {"id": "struct.UnitAny_1_13c_layout_gfx_render_members", "kind": "struct", "status": "sourced", "trust": "sourced", "author": "misiek1294 (phrozen_code Discord)", "module": "", "desc": "UnitAny: dwType 0x00, dwTxtFileNo 0x04, pMemPool 0x08, dwUnitId 0x0C, dwMode 0x10, union pPlayerData/pItemData/... 0x14, dwAct 0x18, pAct 0x1C, seeds 0x20/24/28, pPath 0x2C, dwGfxFrame 0x44, dwFrameRemain 0x48, wFrameRate 0x4C, pAnimData 0x50, pGfxInfo(D2GfxDataStrc*) 0x54, pGfxInfo2 0x58, pStatsEx 0x5C, pInventory 0x60, pLight 0x64, dwLightRadius 0x68, nPalShiftIdx 0x6C, wX 0x8C, wY 0x8E, dwFlags 0xC4, dwFlagsEx 0xC | D2GfxDataStrc* pGfxInfo; //0x54 ... Light * pLight; //0x64 ... WORD nPalShiftIdx; //0x6C", "source": ["discord:phrozen_code msg 385339229879795722"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use"} {"id": "struct.UnitAny_0x6C_union", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "", "desc": "pUnit+0x6C is a union: bool bInteracting / char nPL2Shift (palette-shift index). Confirmed by disasm MOV BL,[ESI+6C] as pPlayer->nInteract | union { bool bInteracting; char nPL2Shift; }; //+6C", "source": ["discord:phrozen_code msg 385523695088828427"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "+0x6C"} {"id": "corpus.D2CMP_crash_address", "kind": "global", "status": "sourced", "trust": "sourced", "author": "AlphA - The Real One (phrozen_code Discord)", "module": "D2CMP", "desc": "Access-violation fault address inside D2CMP.dll (cross-referenced to d2mods thread) | Fault address: 6FE21614 01:00010614 D:\\Spiele\\Diablo II\\D2CMP.dll", "source": ["discord:phrozen_code msg 390833985405845514"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2CMP.dll 6FE21614 (01:00010614)"} {"id": "corpus.D2ReInitRoom", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Game", "desc": "void __fastcall(D2GameStrc* pGame, DRLGRoom* pRoom) - re-initialises a room | D2FUNC(D2GAME,0x85A0,void,__fastcall,D2ReInitRoom,(D2GameStrc* pGame, DRLGRoom* pRoom));", "source": ["discord:phrozen_code msg 393915650268987406"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Game.0x85A0"} {"id": "corpus.Trade_panel_draw_function_1_13c", "kind": "global", "status": "sourced", "trust": "sourced", "author": "misiek1294 (phrozen_code Discord)", "module": "D2Client", "desc": "Function where the trade panel is drawn in 1.13c | function where trade panel are drawn 0x99440 (1.13c)", "source": ["discord:phrozen_code msg 395705736346337280"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x99440"} {"id": "corpus.D2DrawImageToWindow_D2Gfx_10072", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Deleted User (phrozen_code Discord)", "module": "D2Gfx", "desc": "D2Gfx image-blit-to-window function (ordinal 10072) at GfxOffset+0x42A0 | D2DrawImageToWindow = (GfxOffset + 0x42A0); // D2Gfx.10072", "source": ["discord:phrozen_code msg 395696377864257537"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "GfxOffset+0x42A0, D2Gfx.#10072"} {"id": "struct.D2GFXDataStrc_gfx_anim_descriptor_sizeof_0x4", "kind": "struct", "status": "sourced", "trust": "sourced", "author": "misiek1294 (phrozen_code Discord)", "module": "", "desc": "Necrolis authoritative gfx data struct: pCellInit +00, pCellFile +04, nFrame +08, nDirection +0C, nMaxDirections +10, nMaxFrames +14, fFlags +18, fState +1C, nComponent/fItemFlags +1D, nUnitType +20, nUnitIndex +24, nMode +28, nOverlay +2C, union{dwToken +30, dwComponent +34, dwArmorType +38, dwMode +3C, dwHitClass +40} , pName +44. This is UnitAny->pGfxInfo (+0x54) | struct D2GFXDataStrc //sizeof 0x48 { D2GFXCellStrc* pCellInit; //+00 ... const char* pName; //+44 };", "source": ["discord:phrozen_code msg 397384023032201228"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use"} {"id": "corpus.GetItemGfxData_I", "kind": "function", "status": "sourced", "trust": "sourced", "author": "misiek1294 (phrozen_code Discord)", "module": "D2Client", "desc": "Internal item gfx data fetch: (D2GfxDataStrc*, UnitAny*, CellFile*, int nDirection, int nFrame, BYTE fFlags, DWORD dwColorTint, int* pIndex). 1.13c offset 0x6E2C0 confirmed. Various naked __fastcall/__stdcall wrappers posted | D2PTR(D2CLIENT, GetItemGfxData_I,0x6E2C0) //0x6FB1E2C0", "source": ["discord:phrozen_code msg 397419989822341120"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6E2C0 (1.13c) = 0x6FB1E2C0"} {"id": "corpus.Item_quality_color_jumptable_1_13c_client", "kind": "global", "status": "sourced", "trust": "trusted", "author": "Firehawk (phrozen_code Discord)", "module": "D2Client", "desc": "Item gfx setup writes 0xFFFFFFFF to pnUnused via jumptable cases 0-2 (lea esi,[esp+pGfxData]) | jumptable 6FB5CFC7 cases 0-2 ... mov dword ptr [eax], 0FFFFFFFFh", "source": ["discord:phrozen_code msg 397424585286615050"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "jumptable at 6FB5CFC7 / code near 0xACFD7"} {"id": "corpus.WriteCall_hook_helper_D2Client_ingame_loop_h", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Firehawk (phrozen_code Discord)", "module": "D2Client", "desc": "WriteCall(target,source,length): writes 0xE8 call + NOP pad with VirtualProtect. Example hooks the in-game loop at D2Client.dll+0x45EC4 (24-byte patch) to run per-frame code | WriteCall(DWORD(GetModuleHandle(\"D2Client.dll\"))+0x45EC4, DWORD(&InGameLoop), 24);", "source": ["discord:phrozen_code msg 398534469075599370"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client + 0x45EC4"} {"id": "corpus.Item_quality_color_select_1_10_client", "kind": "global", "status": "sourced", "trust": "sourced", "author": "Ogodei (phrozen_code Discord)", "module": "D2Client", "desc": "Item name color selection: calls D2Common.#10695 to get quality, jumptable at 6FB20A14 maps quality-4 to color: rare=9,crafted=8,tempered=0A,magic=3,set=2,unique=4. Also 1.10 variant at 6FAE365B (item-list colors) | CALL ; get item quality ... MOV EBX,9 ; D2_Yellow_Light (rare)", "source": ["discord:phrozen_code msg 405275297160757248"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client near 6FB20772 / calls D2Common.#10695 (get item quality)"} {"id": "corpus.ITEMS_GetCompData", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Common", "desc": "Builds the composite comp/color arrays (nComp[16] +088, nColor[16] +098). eD2CompositeItem enum: HEAD0,TORSO1,LEGS2,RARM3,LARM4,RHAND5,LHAND6,SHIELD7,SPECIAL1-8=8..15,COUNT16,INVALID0xFF | Function: ITEMS_GetCompData Address: D2Common.#10298", "source": ["discord:phrozen_code msg 402572502880092210"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Common.#10298"} {"id": "corpus.Menu_char_draw_loop_start", "kind": "global", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Win", "desc": "Start of the character drawing loop in menus | look at D2Win.0x6F8AD818 for the start of the char drawin loop in menus", "source": ["discord:phrozen_code msg 402573487404875788"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Win.0x6F8AD818"} {"id": "corpus.Window_border_blank_pixel_fix", "kind": "note", "status": "sourced", "trust": "sourced", "author": "misiek1294 (phrozen_code Discord)", "module": "D2Gfx", "desc": "SetWindowLongPtr(D2GFX_GetHwnd(), GWL_STYLE, WS_POPUP|WS_VISIBLE) removes blank/border pixels around the render window | SetWindowLongPtr(D2GFX_GetHwnd(), GWL_STYLE, WS_POPUP | WS_VISIBLE); removes blank pixels", "source": ["discord:phrozen_code msg 402912618345398282"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use"} {"id": "struct.AnimToken_COF_animation", "kind": "struct", "status": "sourced", "trust": "sourced", "author": "eezstreet (cla$$ics) (phrozen_code Discord)", "module": "", "desc": "AnimToken{ D2TokenType tokenType; union{ cof_handle plrCof[PLRMODE_MAX][WC_MAX]; monCof[MONMODE_MAX]; objCof[OBJMODE_MAX]; } }. COFs load with token; .dcc directions loaded lazily per direction needed | struct AnimToken { D2TokenType tokenType; union { cof_handle plrCof[PLRMODE_MAX][WC_MAX]; ... } };", "source": ["discord:phrozen_code msg 404828058453934080"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use"} {"id": "corpus.Custom_GFX_driver_render_TODO_known_bugs", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Glide", "desc": "Necrolis' worklist for a custom OpenGL D2 driver. KEY render-pipeline facts: (1) the driver internally switches EACH draw function between perspective and flat mode - see D2Glide.0x6F814480 - render coords must be fixed and #10068's impact investigated; (2) an 'underlay shader' causes the screen to darken watching fights outside Act V town and breaks GetHit-mode transparent backgrounds on some Act 5 monsters; (3) Mod | internally the driver switchs each draw function between perspective and flat, see D2Glide.0x6F814480, we need to fix the render coords", "source": ["discord:phrozen_code msg 413059147538366465"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Glide.0x6F814480"} {"id": "corpus.Inventory_panel_draw_function", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Mnw1995 (phrozen_code Discord)", "module": "D2Client", "desc": "The function that handles inventory drawing. IMPORTANT for panel work: it ALSO draws the Stash, Cube, and Trade panels, so it's non-trivial to isolate a single panel. Advice: search for the .dc6 names to find the globals that store the panel images. | The function that handles the inventory drawing is located at D2Client.0x3EAC0 ... it also draws the Stash, Cube, Trade Panels", "source": ["discord:phrozen_code msg 417046820229873667"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x3EAC0"} {"id": "struct.AltItem_expanded_item_display_draw_array_ele", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2Client", "desc": "Struct for the expanded on-screen item-display (ALT-highlight) draw array, gptAltDrawArray. Fields: nLeft/nTop/nRight/nBottom rect (+0x00..+0x0C), Unit* pItem (+0x10), wchar_t wszName[128] (+0x14), nRectColor (+0x114), nRectDrawMode (+0x118), nColor (+0x11C). Whist gives a full 1.13c patch table hooking D2Client at 0x58E59/0x59089/0xCDBB9 (max-count patches to 0x7F), and 0x58E83/0x58F07/0x5909D/0x59448/0x58F94/0x58F2 | struct AltItem { int nLeft; int nTop; int nRight; int nBottom; Unit* pItem; wchar_t wszName[128]; int nRectColor; int nRectDrawMode; int nColor; };", "source": ["discord:phrozen_code msg 420017814469083153"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use"} {"id": "corpus.Expanded_item_display_drop_filter_patch_offs", "kind": "global", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2Client", "desc": "1.13c D2Client offsets for the on-floor item-name display (the labels drawn over the play area). 0x58E59/0x59089/0xCDBB9 are the max-count caps (patched to 0x7F). The 0x58Exx/0x59xxx set repoint reads at the rect draw into gptAltDrawArray fields. Drop-filter hook site at 0x5907E (call) / 0x5907F (stub). | {D2DLL_D2CLIENT, 0x58E59, ... Max Count Patch ... {D2DLL_D2CLIENT, 0x58E83, ... Expanded Data Array", "source": ["discord:phrozen_code msg 420017025654587413"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client 0x58E59,0x59089,0xCDBB9,0x58E83,0x58F07,0x5909D,0x59448,0x58F94,0x58F2F,0x58F70,0x5907E"} {"id": "corpus.UNITDRAW_GetComponents", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Necrolis-labeled function returning the component/draw-priority bytes for a unit's COF given rotation+frame. Indexes into the COF trailing arrays: nPos = ((nRotation*nFrames + nFrame + sizeof(D2COFLayerInfoStrc)) * nLayers) + nFrames, then adds sizeof(D2COFStrc). Part of the character/unit sprite render path. | Function: UNITDRAW_GetComponents Address: D2Client.0x6FB5EFC0", "source": ["discord:phrozen_code msg 417290946321973258"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FB5EFC0"} {"id": "corpus.Unit_palette_getter_assigner_incl_Rand_Palet", "kind": "global", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "D2Client.0x6FAAE3C0 gets a unit's palette including Rand Palettes. D2Client.0x6FB28410 is the palette assigner; the three funcs below it compute the secondary index (source is a packet). Necrolis points a second user (Ogodei) to focus mainly on D2Client.0x6FB27A1F. Render/palette-shift relevant. | have a look at D2Client.0x6FAAE3C0 for what gets a units palette (including Rand Palettes). Look at D2Client.0x6FB28410 for the assigner", "source": ["discord:phrozen_code msg 409873812985872404"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FAAE3C0 (getter), 0x6FB28410 (assigner), 0x6FB27A1F"} {"id": "struct.D2CellFileStrc_DC6_cell_file_header", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2CMP", "desc": "Cell-file (sprite) header, sizeof 0x18 + frame data: dwVersion(+00), fCellFlags(+04), nEncodeType(+08), dwPaletteOffset(+0C), nDirections(+10), nFrames(+14), D2GFXCellStrc* pFrames[](+18). Necrolis clarifies 24-bit DC6's aren't really 24-bit - they carry their own PCX-style palette, and the 'zeros' field is the offset to that internal palette. He states he has mapped out most of D2CMP's ordinals. | struct D2CellFileStrc ... DWORD dwPaletteOffset; //+0C ... 24bit DC6's aren't 24bit, they just have their own palette", "source": ["discord:phrozen_code msg 419962996060717067"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use"} {"id": "corpus.DC6_frame_RLE_decode", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2CMP", "desc": "DC6 frame decoder. Pixel byte semantics: 0x80 = end of row (x=0, y--); (pix & 0x80) with other bits = skip/advance x by (pix & 0x7F) transparent pixels; else pix = run length of literal pixels to copy. Necrolis also gives a DWORD-vectorized variant (copy pix/4 dwords then switch on pix&3). Writes into gpDecodeBuffer at p[(y*pw)+x]. | if(pix == 0x80){ x = 0; y--; } else if(pix & 0x80) x += pix & 0x7F; else { while(pix--){ p[(y * pw) + x++] = pFrame->pPixels[++i]; } }", "source": ["discord:phrozen_code msg 413002308381835265"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use"} {"id": "corpus.Smacker_R5G5B5_pixel_pack_bug", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Glide", "desc": "Disasm that packs an R5G5B5 pixel for the Smacker (video) manual-decode path. Necrolis notes the last shift (SHL EDX,2 before final OR) is WRONG - a math error in the original code producing a slightly-off blue channel. | this code is meant to create an R5G5B5 pixel for the smacker (in manual decode), the last shift is wrong because someone can't math good", "source": ["discord:phrozen_code msg 418067037592616961"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6F846ECA-6F846EE7"} {"id": "struct.D2COFStrc_D2COFLayerInfoStrc_animation_COF_l", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "COF animation file layout. D2COFLayerInfoStrc sizeof 0x9: nComponent(+0), bShadow(+1), bSelectable(+2), bOverrideTrans(+3), nTransLevel(+4), hitclass szHitClass[4]/dwHitClass(+5). D2COFStrc sizeof 0x1C: nLayers(+00), nFrames(+01), nDirections(+02), nVersion(+03=0x14), dwUnk(+04), then a union of Yoffset/Xoffset box OR nXpos/nWidth/nYpos/nHeight rect (+08..+14), nAnimRate(+18), nArmType(+19). Trailing: pLayerInfo[nLay | struct D2COFStrc //sizeof 0x1C ... BYTE nAnimRate; //+18 BYTE nArmType; //+19", "source": ["discord:phrozen_code msg 417283339351752714"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use"} {"id": "corpus.D2SetFont_D2Win_10127", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Deleted User (phrozen_code Discord)", "module": "D2Win", "desc": "D2Win ordinal 10127 = D2SetFont, at WinOffset+0x09FF0 (6F8A9FF0). Text-render setup. | D2SetFont = (D2Win10127)(WinOffset + 0x09FF0); // D2Win.6F8A9FF0 #10127", "source": ["discord:phrozen_code msg 407304206907736075"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Win.6F8A9FF0 / WinOffset+0x09FF0 / #10127"} {"id": "corpus.D2CMP_10025_ReadDC6Header", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Lectem (phrozen_code Discord)", "module": "D2CMP", "desc": "signed int __stdcall ReadDC6Header(CelFile* pFile, DC6Header** a2, int a3, int a4). Asserts pFile->dwFlags & CELFILE_24BIT; allocates 4*framesPerDir*directions + sizeof(DC6Header); sets version=6, subVersion = dwFlags & 0xF8, copies directions/framesPerDir; dispatches via off_6FE091C0 table indexed by pFile->gap8. Related build-DC6 code sets subVersion 5 if 24bit else 1. | signed int __stdcall D2CMP_10025_ReadDC6Header(CelFile *pFile, DC6Header **a2, int a3, int a4)", "source": ["discord:phrozen_code msg 419655037283860480"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2CMP #10025"} {"id": "corpus.Health_orb_hover_hit_box_D2Client", "kind": "global", "status": "sourced", "trust": "trusted", "author": "Firehawk (phrozen_code Discord)", "module": "D2Client", "desc": "Bounding-box compares for the health orb hover region: X-left CMP EBX,1E ; X-right CMP EBX,6E ; Y-top LEA ECX,[EAX-4B] ; Y-bottom LEA EDX,[EAX-F]. JL/JG jump to 6FAF8C0E to skip. Screen-UI coordinate math for the bottom-left orb panel. | CMP EBX,1E ; Health Hover X Co-Ordinate Left ... CMP EBX,6E ; Health Hover X Co-Ordinate Right", "source": ["discord:phrozen_code msg 421351037170089984"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FAF8B37..6FAF8B59; branch target 6FAF8C0E"} {"id": "corpus.Mana_orb_hover_hit_box_D2Client", "kind": "global", "status": "sourced", "trust": "trusted", "author": "Firehawk (phrozen_code Discord)", "module": "D2Client", "desc": "Mana orb hover bounding box: MOV ECX,[6FB740DC] base; X-left LEA EDX,[ECX-6F]; X-right ADD ECX,-1F; Y-top LEA ECX,[EAX-4B]; Y-bottom ADD EAX,-0F; branches to 6FAF8CD9. 6FB740DC is a global used as the mana orb X anchor. | MOV ECX,DWORD PTR DS:[6FB740DC] ... LEA EDX,DWORD PTR DS:[ECX-6F] ; Mana Hover X Co-Ordinate Left", "source": ["discord:phrozen_code msg 421351414955114498"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FAF8C0E..6FAF8C3A; global DS:[6FB740DC]; branch 6FAF8CD9"} {"id": "corpus.Force_render_life_mana_text_always_show_hove", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Firehawk / Kieran (phrozen_code Discord)", "module": "D2Client", "desc": "NOP the JL/JG hover-bounds branches (6FAF8B3A/43/4E/59 and 6FAF8C19/24/2F/3A) so orb hover text always renders. To reach the mana-text block, also NOP the epilogue at 6FAFF1E6-6FAFF1F0 (pop edi/esi/ebp/ebx; add esp,25C; retn) or JMP to 6FAFF1F1, so execution falls through from life-text to mana-text rendering. | From 6FAFF1E6 to 6FAFF1F0, you should nop those instructions as well, it'll allow it to continue to the mana text rendering", "source": ["discord:phrozen_code msg 421434246922633217"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FAFF1E6..6FAFF1F0 (epilogue); jmp target 6FAFF1F1"} {"id": "corpus.D2Win_10117_text_draw_call_mana_render_path", "kind": "note", "status": "sourced", "trust": "sourced", "author": "Kieran (phrozen_code Discord)", "module": "D2Client/D2Win", "desc": "1.10 mana-render block calls D2Win.#10117 (LEA ECX,[ESP+20]; SUB EDX,EAX; CALL JMP.&D2Win.#10117) then the standard epilogue; this call is absent in the 1.09 layout. | 6FAFF1E1 |. E8 D2CD0600 CALL ", "source": ["discord:phrozen_code msg 421407546511720449"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FAFF1E1 CALL D2Win.#10117"} {"id": "corpus.TileGetRarity_export", "kind": "function", "status": "sourced", "trust": "sourced", "author": "eezstreet (cla$$ics) (phrozen_code Discord)", "module": "D2Common", "desc": "D2Common export at 6FC711D6 named TileGetRarity (tile rarity accessor). | 6FC711D6 .text Export TileGetRarity", "source": ["discord:phrozen_code msg 421358795822858251"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FC711D6"} {"id": "corpus.TileProjectSerialize_export", "kind": "function", "status": "sourced", "trust": "sourced", "author": "eezstreet (cla$$ics) (phrozen_code Discord)", "module": "D2Common", "desc": "D2Common export at 6FC71668 named TileProjectSerialize (tile projection serialization). | 6FC71668 .text Export TileProjectSerialize", "source": ["discord:phrozen_code msg 421364008495349772"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FC71668"} {"id": "corpus.Frame_timing_globals_D2Client_render_loop", "kind": "global", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "D2 does not hardcode client frame time: 6FB75460 holds ms-per-frame; gdwSkipFramesPerSecond compared to 0x16 (=22? note says D2 uses 25fps) at 6FAAA167; gdwFrameRenderSkip read at 6FAAA2C4. Directly governs the client render/skip cadence. | 6FB75460 contains the numbe of ms per frame ... CMP DWORD PTR DS:[],16", "source": ["discord:phrozen_code msg 426283934511398912"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FB75460 (ms/frame); 6FAAA167 gdwSkipFramesPerSecond; 6FAAA2C4 gdwFrameRenderSkip"} {"id": "corpus.Uncap_FPS_by_nopping_frame_skip_check_1_13", "kind": "note", "status": "sourced", "trust": "sourced", "author": "Deleted User (phrozen_code Discord)", "module": "D2Client", "desc": "NOPping CMP DWORD PTR DS:[6FBD3490],EBX / JNE at 6FAF4E51 raises SP framerate to 64 FPS; 6FBD3490 is the frame-skip gate global in 1.13 D2Client. Also gdwFrameRenderSkip test at 6FAAA2C9 can be NOPped. | nopping this out, increases the framerate to 64 FPS in SP. 6FAF4E51 CMP DWORD PTR DS:[6FBD3490],EBX", "source": ["discord:phrozen_code msg 426440173983760394"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FAF4E51; global 6FBD3490"} {"id": "corpus.Frame_rate_limiter_pattern_render_gate", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Recommended render throttle: hook the render fn with a counter and skip every X render; canonical form 'if(current-last>=target) render();' rather than Sleep-based CPU fix. | void RenderFN() { if(current - last >= target) render(); }", "source": ["discord:phrozen_code msg 426848536219484160"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "RenderFN"} {"id": "struct.COF_Header_layout", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "Lectem (phrozen_code Discord)", "module": "file/COF", "desc": "COF file header: layers,frames,directions,version(=20),unknown1(bitfield e.g. loopAnim),bbox xMin/xMax/yMin/yMax(int32),animRate(int16,256),zeros(int16). Governs animation component layers & bounding box. | uint8_t layers; ... int32_t xMin; int32_t xMax; int32_t yMin; int32_t yMax; int16_t animRate;", "source": ["discord:phrozen_code msg 427895422858690561"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "COF Header"} {"id": "struct.DCC_Header_layout", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "Lectem (phrozen_code Discord)", "module": "file/DCC", "desc": "DCC file header: signature(0x74),version(6),directions(max32),framesPerDir,padding0[3],tag(=1),finalDc6Size. Sprite-encoding header. | uint8_t signature; ///< Magic number for DCC files, must be 0x74", "source": ["discord:phrozen_code msg 427895830901555201"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "DCC Header"} {"id": "corpus.Damage_display_stat_pushes_D2Client", "kind": "global", "status": "sourced", "trust": "sourced", "author": "leekun (phrozen_code Discord)", "module": "D2Client", "desc": "Damage-display code in D2Client pushes (0,2) as stat args at 6FB0CF20 (left-skill damage display?), 6FB0D688 (right-skill damage display?), and 6FB0EE91. D2Game damage-calc stat table at 6FCBE420. Client-side damage panel rendering needs editing alongside D2Game. | 6FB0CF20 . 6A 00 PUSH 0 ... Damage display for left skill?", "source": ["discord:phrozen_code msg 428339699556286464"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FB0CF20, 6FB0D688, 6FB0EE91; D2Game 6FCBE420"} {"id": "struct.Cell_UnitInfo_draw_flags", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Common", "desc": "Item cell draw flags: CELLFLAG_UNIQUE=0x01, CELLFLAG_OVERLAY=0x02, CELLFLAG_CLIENT=0x08, CELLFLAG_SET=0x10. Drive item graphic/overlay drawing. | CELLFLAG_UNIQUE = 0x01, CELLFLAG_OVERLAY = 0x02, CELLFLAG_CLIENT = 0x08, CELLFLAG_SET = 0x10", "source": ["discord:phrozen_code msg 434644209341956108"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "cell flags"} {"id": "struct.Dialog_vtable_deposit_stash_dialogs", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Dialog function-pointer table used by deposit dialogs: pfCreate+00, pfDraw+04, pfMouseScroll+08, pfClickDown+0C, pfClickUp+10, pfMouseMove+14, pfNumpadMove+18, pfKeyScrollUp+1C, pfKeyScrollDown+20, pfKeyScrollRight+24, pfKeyScrollLeft+28. Panel dialog draw+input dispatch. | tDialogDraw pfDraw; // +04 ... pfKeyScrollLeft; // +28", "source": ["discord:phrozen_code msg 438835599974072328"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "dialog vtable +00..+28"} {"id": "struct.AnimDataRecord", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2Common", "desc": "AnimData.d2 record: char szAnimDataName[8]@0x00, DWORD dwFrames@0x08, DWORD dwAnimSpeed@0x0C. Frame count + speed for animations. | char szAnimDataName[8]; //0x00 DWORD dwFrames; //0x08 DWORD dwAnimSpeed; //0x0C", "source": ["discord:phrozen_code msg 438508348120498177"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "AnimDataRecord"} {"id": "corpus.Component_hit_test_loop_unit_selection_AABB", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Lectem (phrozen_code Discord)", "module": "D2Client", "desc": "Unit-selection scans up to 16 (0x10) components: sub_6FB28D90 fetches component AABB, IsComponentSelectable_sub_860F7F0 filters, then point-in-box test (pt.x vs xMin/xMax, y vs yMax/yMin). Note inverted Y (yMax is top). Used for clicking units on the play field. | || pt.x < pAABB.xMin || pt.x > pAABB.xMax || a3 < pAABB.yMax || a3 > pAABB.yMin", "source": ["discord:phrozen_code msg 439322697839935489"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "sub_6FB28D90; sub_860F7F0"} {"id": "corpus.Composite_draw_loop_GetItemGfxData_DrawImage", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Lectem (phrozen_code Discord)", "module": "D2Client/D2gfx", "desc": "Layer draw loop over COF layers: for each selectable component, memset gfx, D2CLIENT_GetItemGfxData_6FB5EC80 fills a CelContext (dir, frame, component), then D2GFX_10076_DrawImageFast(&gfx, pXAdjust, pYAdjust, palette). Iterates layerIdx < cofFile->header.layers. Core unit/item composite rendering. | D2CLIENT_GetItemGfxData_6FB5EC80(...) ... D2GFX_10076_DrawImageFast(&tmpGfxInfo, pXAdjust, pYAdjust, nPaletteIndex[0]);", "source": ["discord:phrozen_code msg 439325860634296322"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2CLIENT 6FB5EC80; D2GFX ord 10076"} {"id": "corpus.Level_id_change_setter_unused_now_entering_g", "kind": "global", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "D2Client.0x6FB00C10 updates the player's level id and sets a global on change (presumably for 'now entering' text), but the globals it sets are unused. | D2Client.0x6FB00C10 updates the level id of the player, and then sets a global when it changes ... the globals it sets are unused", "source": ["discord:phrozen_code msg 443734620425682944"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "0x6FB00C10"} {"id": "corpus.GetUnitOutlineWhenHit_D2Client_sub_7C39DD0", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Lectem (phrozen_code Discord)", "module": "D2Client", "desc": "Computes the outline color index when a unit is hit: lazily inits color indices via D2WIN_10034_GetClosestColorIndex (green 0,C0,0 / yellow E0,E0,0 / red E0,0,0 / blue 0,0,C0); for monsters checks MonStatsFlags bit1 (->blue), else colors by life% (<33 red, <66 yellow, else green). Uses ConvertMode #11013, GetAnimOrSeqMode #10369, QuickGetTotalMaxLife #10564, GetUnitStat #10519. | gGreenColorIndex = D2WIN_10034_GetClosestColorIndex(0, 0xC0u, 0); ... nLifePercentage < 33) return gRedColorIndex", "source": ["discord:phrozen_code msg 440633087261671424"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "sub_7C39DD0; D2WIN #10034"} {"id": "corpus.ITEMS_GetItemPalette_D2Common_10893", "kind": "function", "status": "sourced", "trust": "trusted", "author": "whist / Deleted User (phrozen_code Discord)", "module": "D2Common", "desc": "Returns the color/transform palette for drawing an item: __stdcall(pOwner, pItem, pColor, nTransType). Key gotcha: passing the player as pOwner tints inventory items by the player's palette; must pass NULL as pOwner so inventory items draw with correct colors. | BYTE* __stdcall ITEMS_GetItemPalette(Unit* pOwner, Unit* pItem, BYTE* pColor, int nTransType)", "source": ["discord:phrozen_code msg 441716398629060619"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "#10893"} {"id": "corpus.INVENTORYSCREEN_DrawItem_D2Client_0x6B5A0", "kind": "function", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2Client", "desc": "Draws an item into the inventory/character panel: validates UNIT_ITEM, gets client player, GetItemCacheGfxData + D2CMP_InitGfxData, animates via GfxData.nFrame=((GetTickCount()>>7)+item LoSeed)%nMaxFrames, applies DRAWMODE_TRANS50 for ethereal, then D2GFX_DrawImage(&gfx, nPosX, nPosY+cell->nHeight, -1, drawMode, ITEMS_GetItemPalette(NULL,pItem,&nColor,1)). The pOwner=NULL fix lives here. | INVENTORYSCREEN_DrawItem Address: D2Client.0x6B5A0 ... D2GFX_DrawImage(&GfxData, nPosX, (nPosY + pCell->nHeight), -1, nDrawMode, ITEMS_GetItemPalette(", "source": ["discord:phrozen_code msg 441716537490145283"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "0x6B5A0"} {"id": "corpus.Composite_palette_shift_green_blood_S7_S8_la", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Lectem (phrozen_code Discord)", "module": "D2Client", "desc": "Unit composite draw special-cases COF component letters: S8 layer applies green-blood palshift (GetGreenBloodPalshift) when monStatsEx->nLocalBlood and a client flag (sub_7B8C020); S7 layer resolves a linked unit (sub_7C06AD0) and if missile or in state 143 recurses into UNITDRAW_ProcessUnit_6FB4DB40. Component enum check NUM_COMPONENTS asserts in Composit.cpp:613. | else if ( compByte == S7 ) ... D2CLIENT_UNITDRAW_ProcessUnit_6FB4DB40(v45, dwGamma, 1);", "source": ["discord:phrozen_code msg 443355879056736257"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "UNITDRAW_ProcessUnit 6FB4DB40; sub_7C047F0; sub_7C06AD0"} {"id": "struct.DrlgAct_0x18_DrlgTileData", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2Common", "desc": "1.13c: pDrlgAct + 0x18 holds a DrlgTileData structure (level tile data). | DrlgTileData DrlgTileData; //0x18", "source": ["discord:phrozen_code msg 443950097357864961"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "DrlgAct+0x18"} {"id": "corpus.D2CheckUnitSelectable_D2Client_6FB5F7F0", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "__fastcall(D2UnitStrc* pUnit, D2COFStrc* pCOF) BOOL — determines whether a unit/COF is selectable (mouse-over hit eligibility). | D2Client.6FB5F7F0 BOOL __fastcall D2CheckUnitSelectable(D2UnitStrc* pUnit, D2COFStrc* pCOF)", "source": ["discord:phrozen_code msg 448087216917315597"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FB5F7F0"} {"id": "struct.D2MonSeqTxt", "kind": "struct", "status": "sourced", "trust": "sourced", "author": "Mnw1995 (phrozen_code Discord)", "module": "D2Common", "desc": "Monster sequence record: WORD wSequence@0x00, BYTE nMode@0x02, nFrame@0x03, nDir@0x04, nEvent@0x05. | WORD wSequence; //0x00 BYTE nMode; //0x02 BYTE nFrame; //0x03 BYTE nDir; //0x04 BYTE nEvent; //0x05", "source": ["discord:phrozen_code msg 467350704206512138"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2MonSeqTxt"} {"id": "corpus.gdwClientGameFrame_D2DrawUI", "kind": "global", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "D2Client global holding current client frame counter (drives animrate advancement, runs at 25fps and slows with the client); D2DrawUI is the UI render routine. Necrolis advises hooking the UI drawing to draw text then draw UI, rather than spawning threads. Core render-loop anchors. | 6FBA7768; gdwClientGameFrame\n6FB21B70; D2DrawUI", "source": ["discord:phrozen_code msg 493511122620645386"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FBA7768 (gdwClientGameFrame), 6FB21B70 (D2DrawUI) [1.10]"} {"id": "corpus.UI_INVENTORY_DrawItemBackground", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Mnw1995 (phrozen_code Discord)", "module": "D2Client", "desc": "Draws the colored cell background behind an inventory item, given the grid-info struct, X/Y, item width/height in cells, and a color index. Side-panel (inventory) rendering primitive. | void __fastcall UI_INVENTORY_DrawItemBackground(D2InventoryGridInfoStrc* pInventoryGridInfo, int nX, int nY, BYTE nItemWidth, BYTE nItemHeight, DWORD ", "source": ["discord:phrozen_code msg 481041433692733440"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FAE1710"} {"id": "corpus.UI_INVENTORY_LoadItemBackgroundColors", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Mnw1995 (phrozen_code Discord)", "module": "D2Client", "desc": "Loads the inventory item-background colors in advance (paired with UI_INVENTORY_DrawItemBackground). | void __fastcall UI_INVENTORY_LoadItemBackgroundColors()", "source": ["discord:phrozen_code msg 481042639874031618"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FADD2F0"} {"id": "struct.D2InventoryGridInfoStrc", "kind": "struct", "status": "sourced", "trust": "sourced", "author": "Mnw1995 (phrozen_code Discord)", "module": "", "desc": "Layout of an inventory grid panel: grid cell counts (X/Y), the pixel bounds of the grid (left/right/top/bottom) and per-cell box width/height. This is the geometry of a side panel's item grid. | int nGridLeft;//0x04 ... int nGridBottom;//0x10 BYTE nGridBoxWidth;//0x14 BYTE nGridBoxHeight;//0x15", "source": ["discord:phrozen_code msg 481048950934077440"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "sizeof 0x18; nGridLeft +0x04, nGridRight +0x08, nGridTop +0x0C, nGridBottom +0x10, nGridBoxWidth +0x14, nGridBoxHeight +0x15"} {"id": "corpus.sub_6FAE0DC0_DrawInventoryItemSockets", "kind": "function", "status": "sourced", "trust": "sourced", "author": "misiek1294 (phrozen_code Discord)", "module": "D2Client", "desc": "Draws socket overlays in the inventory grid. Signature sub_6FAE0DC0(UnitAny* ptItem, InventoryGrid* pGrid, int nLeft, int nBottom). Uses a socket-position lookup array (first 2 dwords = where socket should be drawn, then 10 zero dwords per entry). 1.13c client base is 0x6FAA0000. | void __fastcall sub_6FAE0DC0(UnitAny *ptItem, InventoryGrid *pGrid, int nLeft, int nBottom)", "source": ["discord:phrozen_code msg 488335503196684291"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FB45140 (1.13c) / 6FAE0DC0 (1.10) = offset 0x40DC0; socket-position array 6FB80A98 (1.13c \\ 0xD0A98) / 6FB6EFD0 (1.10 \\ 0xBEFD0)"} {"id": "corpus.UI_INVENTORY_socket_item_draw_internals", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Lectem (phrozen_code Discord)", "module": "D2Client / D2Common / D2gfx", "desc": "Decompiled socket-drawing loop: indexes gSocketPositions by [height + 4*(width + 2*nbSockets) - 13], computes cell-centered X/Y from nGridBoxWidth/Height, sets up a D2GfxData with pCelFile = GEMSOCKET cellfile global (0x6FBB5E34) and calls D2GFX ordinal #10072 DrawImage, then draws each socketed item via DrawInventoryItems at 0x6FB5A320. Panel item/socket render pipeline. | pData.pCelFile = (CelFile *)gpCellfile_GEMSOCKET_6FBB5E34; D2GFX_10072_DrawImage(&pData, v10 - 1, v12, -1, 0, 0);", "source": ["discord:phrozen_code msg 488355263984697346"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "gSocketPositions array; D2GFX_10072_DrawImage; gpCellfile_GEMSOCKET_6FBB5E34; D2CLIENT_UI_INVENTORY_DrawInventoryItems_6FB5A320; ordinals D2COMMON_10749_GetItemDimensions, 10816_GetItemSockets, 10277/10304/10305"} {"id": "corpus.UNITDRAW_CheckSelection", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Checks whether a unit is the current selection target during unit drawing; called from the unit-draw routine at 0x6FB5A720. Part of the play-area unit render path. | BOOL __fastcall UNITDRAW_CheckSelection(D2UnitStrc* pUnit) // D2Client.0x6FB286B0", "source": ["discord:phrozen_code msg 496659829150973962"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FB286B0; caller at D2Client.0x6FB5A720"} {"id": "corpus.Palette_shift_texture_rendering_monster_pals", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2gfx/D2CMP", "desc": "Necrolis's custom renderer notes: D2 makes 8 palette copies for any unit with a palshift.dat; PL2/randshift are created ad hoc; DCC/DC6 must stay resident for reshifting. His approach decodes the DCC/DC6, builds an L8 or HW-compressed GPU texture, frees the source, and on palshift just changes the index (offset) into the palette LUT (or a shader switch for shadow/HW-compressed textures). Notes D2 poorly caches D2GetN | the way D2 handles monsters with a palshift.dat means that if its present, \"8 copies\" are made", "source": ["discord:phrozen_code msg 492103907137290260"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2GetNearestPaletteIndex, D2SetPalette"} {"id": "struct.D2_Tile_TileHeader_DT1", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "", "desc": "Layout of the DT1 floor/wall tile header used by the map renderer, including per-tile collision bitmap (25 bytes), runtime cache index, block offset, light direction, roof height, dimensions, type/style/sequence, and 24-bit transparent color. Direct floor/tile rendering data. | uint8_t fCollisionInfo[25];//+28 ... uint16_t wCacheIndex;//+42 - runtime only ... uint32_t dwBlockOffset;//+48", "source": ["discord:phrozen_code msg 488458275394682890"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "fCollisionInfo[25] +0x28, wCacheIndex +0x42 (runtime), dwBlockOffset +0x48; also dwLightDirection, roofHeight, wFlags, dwTotalHeight, dwWidth, dwHeightToBottom, dwType, dwIndex_Style, dwSubIndex_Sequence, transparentColorRGB24"} {"id": "struct.D2SubTileStrc", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "", "desc": "Sub-tile (tile component) descriptor for DT1 rendering: screen X/Y, grid X/Y, pixel format, encoded length, and offset/pointer to the pixel data block. | struct D2SubTileStrc //sizeof 0x14 { short nXpos;//+00 short nYpos;//+02 ... uint16_t wFormat;//+08 int nLength;//+0A", "source": ["discord:phrozen_code msg 488463133657137173"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "sizeof 0x14; nXpos +00, nYpos +02, nGridX +06, nGridY +07, wFormat +08, nLength +0A, dwOffset/pData +10"} {"id": "corpus.Tile_SubTile_GFX_material_flag_enums", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2CMP", "desc": "Full flag/enum sets for tile libraries, sub-tile walkability/LoS/light collision, tile materials, and tile-component encoding (run-length, gamesquare). Governs floor tile behavior and decoding. | TILE_NOWALK=0x01, TILE_NOLOSLIGHT=0x02, TILE_NOJUMPTELEPORT=0x04, TILE_NOPLAYERWALK=0x08, TILE_NOLIGHT=0x20", "source": ["discord:phrozen_code msg 488466029635305472"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "eD2TileFlags (TILELIB_RAW 0x01, HASTILES 0x02, INITED 0x04, FEWTILES 0x08), eD2SubTileFlags (NOWALK 0x01, NOLOSLIGHT 0x02, NOJUMPTELEPORT 0x04, NOPLAYERWALK 0x08, NOLIGHT 0x20), eD2GFXTileMaterials, TILECOMP flags (RLE 0x1000, GAMESQUARE 0x2000)"} {"id": "corpus.D2Parse24BitTileLibrary_D2Load24BitTileLibra", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2CMP", "desc": "Ordinal exports that parse/load a 24-bit tile library, taking a per-pixel RGB mapping callback. Part of the DT1 tile-loading pipeline for the floor renderer. | 10074 void __stdcall D2Parse24BitTileLibrary(D2TileLibraryStrc* pLibrary, void (__stdcall* pfMap)(DWORD dwRGB))", "source": ["discord:phrozen_code msg 501039410721193984"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "ordinals #10074, #10075"} {"id": "struct.DT1_file_Header", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "Lectem (phrozen_code Discord)", "module": "", "desc": "On-disk DT1 tile-library header layout for both current (v7) and older (v4) formats; v4's skipColor is the RGB skipped in D2CMP CelIteratePixels. Floor/tile file format. | uint32_t version; ... if(version == 7){ char libraryName[260]; uint32_t numTiles; uint32_t firstTile; }", "source": ["discord:phrozen_code msg 501043385780404227"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "version +0 (7 or 4), flags +4, then libraryName[260]/numTiles/firstTile (v7) or numTiles/skipColor[4] (v4)"} {"id": "corpus.D2CLIENT_GetItemGfxData", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Mnw1995 (phrozen_code Discord)", "module": "D2Client", "desc": "Fills a D2GfxDataStrc for an item given cell file, direction, frame, component and mode. Item graphic-data resolver used in inventory/ground rendering. | BOOL __fastcall D2CLIENT_GetItemGfxData_6FB5EC80(D2GfxDataStrc* pGfxData, D2UnitStrc* pItem, D2CellFileStrc* pCellFile, int nDirection, int nFrame, in", "source": ["discord:phrozen_code msg 472101142554345473"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FB5EC80 (1.13c)"} {"id": "struct.Rooms_Act_active_room_fields_GetActiveRooms", "kind": "struct", "status": "sourced", "trust": "sourced", "author": "misiek1294 (phrozen_code Discord)", "module": "", "desc": "Level/room bookkeeping offsets; nRooms increments on room init while nActiveRooms tracks active count. GetActiveRooms(Act* pAct, int dwLevelNo). Relevant to map streaming around the play area. | int nRooms;//0x004 ... int nActiveRooms;//0x00C ... GetActiveRooms ... -10662", "source": ["discord:phrozen_code msg 479915531269308416"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "nRooms +0x004, nActiveRooms +0x00C; D2COMMON GetActiveRooms ordinal -10662"} {"id": "struct.D2ObjectsTxt_frame_fields", "kind": "struct", "status": "sourced", "trust": "sourced", "author": "misiek1294 (phrozen_code Discord)", "module": "", "desc": "Objects.txt runtime record has a frame-count array around offset 0xD8-0xD9 (pad0xD8 then dwFrameCnt[7]); relevant to object animation frame rendering. | BYTE pad0xD8;//0xD8 DWORD dwFrameCnt[7];//0xD9", "source": ["discord:phrozen_code msg 469545965926481936"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "pTxt+0xDC region; dwFrameCnt / nFrameCount[8] near +0xD8/0xD9"} {"id": "corpus.1_07_resolution_string_s1280x800", "kind": "note", "status": "sourced", "trust": "sourced", "author": "Deleted User (phrozen_code Discord)", "module": "D2Game", "desc": "1.07 references a resolution-config string 's1280x800(1).left' at 6FD447C8 - suggests table-driven screen-region layout keys. | MOV ECX,DWORD PTR DS:[6FD447C8] ; ASCII \"s1280x800(1).left\"", "source": ["discord:phrozen_code msg 495483842472443915"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FD447C8 ASCII \"s1280x800(1).left\""} {"id": "struct.D2FloorTileParamsStrc", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "The parameter struct passed to the D2Client floor/tile-drawing routine. Directly names the render-pipeline fields we care about: nScreenPanels at +0x20 (which side panels are open), pView (D2ViewStrc*) at +0x24, bDrawEdgeTiles at +0x28, tile bounds nXMin/nXMax/nYMin/nYMax at +0x2C..+0x38, and the crucial nViewXOffset (+0x3C) and nViewYOffset (+0x40, typo'd nnViewYOffset). This is the screen-shift/dead-zone control bl | struct D2FloorTileParamsStrc //sizeof 0x44 - D2Client.0x6FB9A990 { ... int nScreenPanels; //+20 D2ViewStrc* pView; //+24 ... int nViewXOffset; //+3C ", "source": ["discord:phrozen_code msg 526879393868677131"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FB9A990 (sizeof 0x44)"} {"id": "struct.TileGfxData", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2gfx", "desc": "Whist's (incomplete) definition of the struct passed to the d2gfx tile-drawing ordinals; only szDT1FileName mapped at +0x058 (the DT1 tile file name), first 0x58 bytes unknown. | struct TileGfxData { DWORD __000[88]; //0x000 char* szDT1FileName; //0x058 };", "source": ["discord:phrozen_code msg 526876350586290177"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "+0x058"} {"id": "corpus.tile_drawing_setup_fn_D2Client_6FAA3330", "kind": "function", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2Client", "desc": "Whist identifies D2Client 6FAA3330 (1.10f) as where the tile-draw params struct is set up; Lectem notes one member is ptRect at +0x24 (matches pView slot in the 1.13c struct). Confirms the floor-render param block is built here before the d2gfx tile ordinals are called. | only def I have is the struct that gets passed to the tile drawing d2gfx ordinals and it's really incomplete", "source": ["discord:phrozen_code msg 526876302762967050"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FAA3330 (1.10f); member ptRect +0x24"} {"id": "corpus.PATH_ScreenToWorld", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Common", "desc": "Screen->world isometric coordinate transform (D2Common ordinal #10108). nX*=2; outX=(nX+nY)>>5; outY=(nX-nY)>>5. Core camera/iso projection math used when converting cursor/screen to tile world coords. | PATH_ScreenToWorld ... nXpos *= 2; *pXpos = (nXpos + nYpos) >> 5; *pYpos = (nXpos - nYpos) >> 5;", "source": ["discord:phrozen_code msg 508793089893203969"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Common.#10108"} {"id": "corpus.PATH_WorldToScreen", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Common", "desc": "World->screen isometric transform (D2Common #10111): outX=(nX-nY)<<4; outY=(nX+nY)<<3. The inverse projection that places world tiles onto the play-area viewport. | PATH_WorldToScreen ... *pXpos = (nXpos - nYpos) << 4; *pYpos = (nXpos + nYpos) << 3;", "source": ["discord:phrozen_code msg 509106529522286592"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Common.#10111"} {"id": "corpus.PATH_FlattenCoords", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Common", "desc": "D2Common #10112 coordinate flatten: outX=(nX-nY)>>1; outY=(nX+nY)>>2. Another iso coordinate transform in the path/render coordinate family. | PATH_FlattenCoords ... *pXpos = (nXpos - nYpos) >> 1; *pYpos = (nXpos + nYpos) >> 2;", "source": ["discord:phrozen_code msg 509106529522286592"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Common.#10112"} {"id": "corpus.DUNGEON_TILES_ExpandCoords_DUNGEON_ExpandCoo", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Common", "desc": "Tile coordinate expansion helpers: DUNGEON_TILES_ExpandCoords = D2Common #10110, DUNGEON_ExpandCoords = D2Common #10113. Part of the dungeon-tile coordinate transform set. | DUNGEON_TILES_ExpandCoords ... Address: D2Common.#10110 ... DUNGEON_ExpandCoords ... Address: D2Common.#10113", "source": ["discord:phrozen_code msg 509117621606678528"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "#10110 and #10113"} {"id": "corpus.Perspective_scale_SetPerspectiveScale_usage", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Lectem (phrozen_code Discord)", "module": "D2gfx/D2Client", "desc": "Decompiled render code showing D2GFX_10010_CheckPerspective gating a block that reads player X/Y (D2COMMON #10327 GetXPos / #10330 GetYPos), calls D2Common_10108 (ScreenToWorld) on shifted coords, then D2GFX_10064_SetPerspectiveScale(playerX,playerY). Names the perspective-mode camera-scale ordinals: D2GFX #10010 CheckPerspective, #10064 SetPerspectiveScale; GetPlayerUnit at D2Client.6FB283D0. | if ( D2GFX_10010_CheckPerspective() ) { ... D2GFX_10064_SetPerspectiveScale(nPlayerPosX, nPlayerPosY); }", "source": ["discord:phrozen_code msg 508766459896266783"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2GFX #10010, #10064; D2Client.6FB283D0; D2COMMON #10327/#10330"} {"id": "struct.InventoryGrid", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2Client/D2Common", "desc": "Layout of the inventory-panel grid array (Inventory+0x14 -> pInvInfo points to array of these). Fields: pFirstItem +0x00, pLastItem +0x04, nWidth +0x08, nHeight +0x09, ppItems (grid cell pointer array) +0x0C. Grid index enum: BODYLOC=0, BELT=1, INVENTORY=2. | struct InventoryGrid { Unit* pFirstItem; //0x00 ... BYTE nWidth; //0x08 BYTE nHeight; //0x09 ... Unit** ppItems; //0x0C };", "source": ["discord:phrozen_code msg 522875920848257024"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "Inventory+0x14 -> array; fields +0x00..+0x0C"} {"id": "corpus.CtrlPnl7_800CtrlPnl7_control_panel_gfx_load", "kind": "note", "status": "sourced", "trust": "sourced", "author": "Burznazg (phrozen_code Discord)", "module": "D2Client", "desc": "Client UI setup reads mpq file '800CtrlPnl7' if a GFX function returns 2, otherwise 'CtrlPnl7' (the actual control-panel UI DC6). The gating GFX function is ordinal for 0x6FAD7290 in 1.13c. 800-prefix appears to be a legacy/alt-resolution variant. | code tries to read file from mpq called 800CtrlPnl7 if some GFX function will return 2. If it returns something else then CtrlPnl7 is readed ... Ordin", "source": ["discord:phrozen_code msg 512033167343878145"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FAD7290 (1.13c)"} {"id": "corpus.Draw_both_weapons_UI_patch_menu_panel_draw_f", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Necrolis patch around D2Client 6FAF8AE0..6FAF8C40 that redirects control flow (JMP/CALL Ordinal10117, then MOV [ESP+20],0) so both items draw in a menu control. Ordinal10117 is a D2Client draw helper; region is a UI/menu-control draw routine. | 6FAF8B38 | CALL 6FAF8B3D | JMP d2client.6FAF8C40 ... MOV DWORD PTR SS:[ESP+20],0", "source": ["discord:phrozen_code msg 522092900910366733"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FAF8AE0 start; calls Ordinal10117"} {"id": "corpus.Unit_flags_0xC4_0xC8_semantics", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Blighthorn / Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Unit flags at +0xC4: 0x01 = tells game to update the unit, 0x20 = whether to draw a shadow (client-only). FlagsEx +0xC8: 0x02000000 = expansion unit, 0x00000004 = spawned in vendor shop, 0x10 (server) = seed initialized (signals sync packet). Necrolis confirms 0x20 is a client-only draw flag. | 0x00000020 - whenever to draw a shadow or not ( client only )", "source": ["discord:phrozen_code msg 505008822432170015"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "+0xC4 bit 0x20 (draw shadow, client-only)"} {"id": "corpus.D2Common_dll_export_ordinal_table_base_6fd40", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Lectem (phrozen_code Discord)", "module": "D2Common", "desc": "Lectem posts the start of a full D2Common 1.13c ordinal->address->name table: #10000 GetLevelType @6fd75260, #10001 GetActNoFromLevelId @6fd75300, #10002 GetLOSDraw @6fd75350, #10005 GetLevel @6fd749a0, #10006 InitLevel @6fd74c10, #10007 GetRoomExFromRoom @6fd8d0c0, #10010 GetLevelDefsRecord @6fd60d90, #10011 GetAutomapCell @6fd62d30, #10012 FreeDrlgAndLevels @6fd743b0, etc. | // List of D2Common.dll exports (base address 6fd40000) ... D2COMMON_10000_GetLevelType ... @address 6fd75260", "source": ["discord:phrozen_code msg 516404860220866571"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Common base 6fd40000; e.g. #10000 @6fd75260"} {"id": "corpus.D2GetRoomList_D2PlaySound_offsets", "kind": "note", "status": "sourced", "trust": "sourced", "author": "Deleted User (phrozen_code Discord)", "module": "D2Common/D2Client", "desc": "D2GetRoomList = D2Common.10035 @0x4BC10; D2PlaySound = D2Client.6FB55820 @0xB5820. Room-list retrieval feeds the render room iteration. | static D2Common2733 D2GetRoomList = (D2Common2733)(0x4BC10 + CommonOffset); // D2Common.10035", "source": ["discord:phrozen_code msg 523293550876557312"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Common 0x4BC10 (#10035); D2Client 0xB5820"} {"id": "struct.D2GameViewStrc", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "Lectem (phrozen_code Discord)", "module": "D2Client", "desc": "The per-view render struct that controls the play-area viewport: dwFlags, ViewRadius (RECT), CheckRadius (RECT), nOffsetX/nOffsetY screen offsets, three Gouraud lighting tables, and embedded render data. This is the struct passed to every tile-draw call as pView. | struct D2GameViewStrc { int dwFlags; RECT ViewRadius; RECT CheckRadius; int nOffsetX; int nOffsetY; ...", "source": ["discord:phrozen_code msg 526881074907971584"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use"} {"id": "corpus.rain_storm_wind_factor_float", "kind": "global", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Float global at 6FBA763C is the storm wind factor (governs rain slant); part of the weather/particle system tied to the ground-tile draw params. | its the storm wind factor IIRC", "source": ["discord:phrozen_code msg 526885477832458251"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FBA763C"} {"id": "corpus.floor_tile_draw_prologue_6FAA2E95", "kind": "global", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Disassembly inside the ground-tile drawing routine (reads [EBX+24], adds 0x14 = the -20/0xFFFFFFEC pView sentinel check). Part of MULTIRES_DrawGroundTiles at 6FAA2E60/2E70. | 6FAA2E95 |. 8B43 24 MOV EAX,DWORD PTR DS:[EBX+24]", "source": ["discord:phrozen_code msg 526894733881114655"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FAA2E95"} {"id": "corpus.RainDrawAndPlaySounds_thunder_bool", "kind": "global", "status": "sourced", "trust": "trusted", "author": "Lectem (phrozen_code Discord)", "module": "D2Client", "desc": "6FAA8240 is RainDrawAndPlaySounds; 6FBA76AC is a boolean that triggers the thunder1 sound. Weather effects driven off the tile-draw frame counters. | 6FAA8240 is actually RainDrawAndPlaySounds", "source": ["discord:phrozen_code msg 527587584713555971"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FAA8240, 6FBA76AC"} {"id": "corpus.Waypoint_panel_draw_WindowStartX_NegWindowSt", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Thaison (phrozen_code Discord)", "module": "D2Client", "desc": "Waypoint-panel drawing loop: WaypointTable at D2CLIENT 0xFCD8C, WaypointCoordTable at 0xDE6D8. Every cell/text is drawn at (*D2CLIENT_WindowStartX + coordTable->nX, coordTable->nY - *D2CLIENT_NegWindowStartY) via D2GFX_DrawCellContext / D2WIN_DrawText. Shows how side-panel UI is offset by the WindowStartX / NegWindowStartY globals -- directly relevant to panel-vs-playarea coordinate origin. | D2GFX_DrawCellContext(&pData, *D2CLIENT_WindowStartX + ptCoordTable->nX, ptCoordTable->nY - *D2CLIENT_NegWindowStartY, ...)", "source": ["discord:phrozen_code msg 528119379787776000"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "0xFCD8C, 0xDE6D8"} {"id": "corpus.MULTIRES_DrawRoofTiles", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "D2Client.0x6FAA3B90 -- draws roof tile layer for the play area, takes D2ViewStrc* pView. | //D2Client.0x6FAA3B90 void __fastcall MULTIRES_DrawRoofTiles(D2ViewStrc* pView)", "source": ["discord:phrozen_code msg 539078647253041172"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FAA3B90"} {"id": "corpus.MULTIRES_DrawUpperWallTiles", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "D2Client.0x6FAA63E0 -- draws upper wall tiles; takes a D2DrawSlotStrc, a bOnlyShadows flag, and pView. | void __fastcall MULTIRES_DrawUpperWallTiles(D2DrawSlotStrc* pDrawSlot, BOOL bOnlyShadows, D2ViewStrc* pView)", "source": ["discord:phrozen_code msg 539078647253041172"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FAA63E0"} {"id": "corpus.MULTIRES_DrawLowerWallTiles", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "D2Client.0x6FAA6670 -- draws lower wall tiles; takes pView. | void __fastcall MULTIRES_DrawLowerWallTiles(D2ViewStrc* pView)", "source": ["discord:phrozen_code msg 539078647253041172"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FAA6670"} {"id": "corpus.MULTIRES_DrawGroundTiles", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "D2Client.0x6FAA2E60 & D2Client.0x6FAA3330 -- draws the ground tile layers; takes pView. This is the core floor/ground draw pair that Lectem's dFloor snippets belong to. | //D2Client.0x6FAA2E60 & D2Client.0x6FAA3330 void __fastcall MULTIRES_DrawGroundTiles(D2ViewStrc* pView)", "source": ["discord:phrozen_code msg 539078647253041172"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FAA2E60 & 0x6FAA3330"} {"id": "struct.D2DrawSlotStrc", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "sizeof 0x24 render batching struct: nStart(+08), nEnd(+0C), then five linked lists of D2UnitDrawStrc -- pShadows(+10), pUpperWallTiles(+14), pUnits(+18), pRoofTiles(+1C), pLowerWallTiles(+20). This is the per-slot draw list that orders shadows/walls/units/roofs in the play area. | struct D2DrawSlotStrc { ... D2UnitDrawStrc* pShadows; //+10 ... pLowerWallTiles; //+20 };", "source": ["discord:phrozen_code msg 539080579019309087"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "sizeof 0x24"} {"id": "struct.eD2TileDataFlags_draw_control_flags", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Tile dwFlags bit meanings: 0x4000 DRAW_GROUND (layers 1-4), 0x8000 DRAW_FLOOR (trans tiles above ground e.g. fog), 0x10000 DRAW_ROOF, 0x20000 DRAWN, 0x40000 REVEALED, 0x8 HIDDEN, 0x400 FADED. DRAWCTRL mask = ROOF|FLOOR|GROUND; remaining layers are shadow. Governs which layer a tile draws in. | TILEFLAG_DRAW_GROUND = 0x00004000, //these are tile layers 1,2,3,4 ... TILEFLAG_DRAW_ROOF = 0x00010000", "source": ["discord:phrozen_code msg 539078150743654410"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "0x4000/0x8000/0x10000"} {"id": "corpus.floor_tile_draw_order_stepping", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Lectem (phrozen_code Discord)", "module": "D2Client", "desc": "Ground tiles are drawn in draw-order steps 1..2 selected by ((dwFlags>>14)&7); DrawOrderMask = 0x7<<14 (0x4000|0x8000|0x10000). Each tile drawn via D2Client_Draw_dFloor_6FAA2E70 with position = ptTileDrawParams->nViewXOffset + tile width and nnViewYOffset + tile height, plus pos*5. Lectem also notes 0x10000 can mean 'do not draw'. Shows the exact viewport-offset math applied to floor tiles. | D2Client_Draw_dFloor_6FAA2E70(ptTileDrawParams, pFloorTileData, v18, ptTileDrawParams->nViewXOffset + pFloorTileData->nWidth, ptTileDrawParams->nnView", "source": ["discord:phrozen_code msg 539057436447997952"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FAA2E70; mask 0x7<<14"} {"id": "corpus.BOTTOM_PANEL_47px_clear_adjustment_0x2F", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2DDraw", "desc": "CRITICAL PANEL FACT: In the D2DDraw screen-clear/blit, the constant 0x2F (47) is the adjustment for the bottom panel -- the game deliberately never clears the last 47px of the screen. 6F8D01C8 is the screen front buffer being cleared; if your custom back buffer is smaller than the sizes passed here you get a buffer overflow / HOM. Directly explains uncleared dead-zones tied to panel geometry. | if you see 0x2F you now its the adjustment for the bottom panel, as the game never clears the last 47px... 6F8D01C8 is the screen front buffer thats b", "source": ["discord:phrozen_code msg 534391420790767637"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "0x2F (47px); 6F8D01C8"} {"id": "corpus.D2DDraw_screen_clear_blit_REP_STOS", "kind": "global", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2DDraw", "desc": "The screen-clear routine at D2DDraw ~6F8C637A: loads front-buffer ptr from 6F8CF8A8, height/pitch from 6F8D01D8, width factor from 6F8D01C8; when a flag (ESI) is set it does ADD ECX,-2F (the 47px bottom-panel adjust) before IMUL. Zeroes the buffer with REP STOS at 6F8C639B. On failure pushes 'Blit (screen clear) failed!' string at 6F8CCE64. This is the exact HOM/dead-zone clear path. | 6F8C638C 83C1 D1 ADD ECX,-2F ... 6F8C639B F3:AB REP STOS DWORD PTR ES:[EDI] ... Blit (screen clear) failed!", "source": ["discord:phrozen_code msg 534388952040341515"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6F8C637A; 6F8CF8A8; 6F8D01C8/01D8; str 6F8CCE64"} {"id": "corpus.DDRAW_surface_dims_800x600_0x320_0x258", "kind": "global", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "ddraw", "desc": "The buffer descriptor built in ddraw (505BEA43+): stores 0x320 (=800) and 0x258 (=600) as surface width/height, sourced from the DDSURFACEDESC at [ESI+1C]/[ESI+1E]. Confirms the front-buffer geometry the 47px clear operates on. | MOV DWORD PTR DS:[EDX+C],EAX ; 0x320 ... MOV DWORD PTR DS:[EDX+8],EAX ; 0x258", "source": ["discord:phrozen_code msg 534400541803937813"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "0x320=800, 0x258=600"} {"id": "corpus.MULTIRES_SetResolution", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "D2Client.0x6FAA23B0. Sets gdwScreenWidth/Height (640x480 or 800x600), sets gpExpansionUI, then gdwViewWidth = gdwScreenWidth and gdwViewHeight = gdwScreenHeight - kMultiResolutionUIHeightAdjustment. Calls MULTIRES_ResolutionChanged, MULTIRES_UpdateView(*gdwScreenPanels), D2ResizeAutomap, D2ResizeDialogs. THE function that derives the play-area view size from screen size minus UI height -- core to panel/viewport layou | *gdwViewWidth = *gdwScreenWidth; *gdwViewHeight = *gdwScreenHeight - kMultiResolutionUIHeightAdjustment; ... MULTIRES_UpdateView(*gdwScreenPanels);", "source": ["discord:phrozen_code msg 545248557578453002"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FAA23B0"} {"id": "corpus.D2WIN_ResizeWindow_10176", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Nightshades (phrozen_code Discord)", "module": "D2Win", "desc": "D2WIN.0x17B60 (ordinal #10176), __stdcall(nResolutionMode). Passes the resolution mode down to D2GFX #10025 to resize the window rect. | D2FUNC(D2WIN, ResizeWindow, void, __stdcall, (int nResolutionMode), 0x17B60);//D2WIN.#10176 - Pass resolution mode to D2GFX.#10025", "source": ["discord:phrozen_code msg 545299582767202312"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2WIN.0x17B60 / #10176"} {"id": "corpus.D2GFX_SelectResolutionMode_10025", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Nightshades (phrozen_code Discord)", "module": "D2gfx", "desc": "D2GFX.0x7FD0 (ordinal #10025). Maps resolution mode -> out RECT right/bottom: 0=640x480, 1/2=800x600, 3=1344x700, default=0x0. Selects resolution mode and resizes the window rect. | D2FUNC(D2GFX,SelectResolutionMode,void,__stdcall,(int nResolutionMode,int *Out_RECT_right,int *Out_RECT_Bottom),0x7FD0)", "source": ["discord:phrozen_code msg 545313909503164420"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2GFX.0x7FD0 / #10025"} {"id": "corpus.D2CLIENT_ScreenXShift", "kind": "global", "status": "sourced", "trust": "sourced", "author": "misiek1294 (phrozen_code Discord)", "module": "D2Client", "desc": "D2CLIENT INT global at 0x11C418 (1.13c) named ScreenXShift -- the horizontal screen/camera shift value. Directly the 'screen SHIFT' global for the play-area viewport. | D2VAR(D2CLIENT, ScreenXShift, INT, 0x11C418)//1.13c", "source": ["discord:phrozen_code msg 545318831799926809"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "0x11C418 (1.13c)"} {"id": "corpus.PAL_Update_PAL_SetUpdate", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Win", "desc": "D2Win #10179 = PAL_Update() (applies palette); D2Win #10176 = PAL_SetUpdate(BOOL) sets the palette globals to activate/deactivate the update. (Note ordinal #10176 also cited for ResizeWindow -- version ambiguity to watch.) | //D2Win.#10176 void __fastcall PAL_SetUpdate(BOOL bActive) ... activate or deactivate D2Win.#10179", "source": ["discord:phrozen_code msg 545235264134447105"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Win.#10179 / #10176"} {"id": "struct.ParticleData", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "Lectem (phrozen_code Discord)", "module": "D2Client", "desc": "Weather/particle entry: dataArrayVersion, nPosX, nPosY, dwSomeThresholdForSin (destroys particle randomly by Y position), nSizeIdx, a boolean, colorIdx, alpha. align(4). | struct ParticleData { ... DWORD dwSomeThresholdForSin; // Used to destroy the particle randomly based on the Y position ...", "source": ["discord:phrozen_code msg 527568540547678208"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use"} {"id": "struct.RainParticleData", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "Lectem (phrozen_code Discord)", "module": "D2Client", "desc": "Splash/bubble particle: dataArrayVersion, nXpos, nYpos, nWhichRain, nCurFrame, rainGfxIdx. Used for rain ripples/bubbles on water tiles. | struct RainParticleData { ... DWORD nWhichRain; DWORD nCurFrame; DWORD rainGfxIdx; };", "source": ["discord:phrozen_code msg 527568826834092032"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use"} {"id": "struct.D2AutoMapCacheStrc_D2AutoMapCellStrc", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Automap cache linked-list node: array of 512 automap cells plus a pPrev link. The automap-overlay data structure sitting over the play area. | struct D2AutoMapCacheStrc //sizeof 0x2804 { D2AutoMapCellStrc pCells[512]; //+0000 D2AutoMapCacheStrc* pPrev; //+2800 };", "source": ["discord:phrozen_code msg 553938339493838858"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "sizeof 0x2804; pCells[512] +0x0000, pPrev +0x2800"} {"id": "corpus.gpAutoMapCache_gnAutoMapCaches", "kind": "global", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Global pointer to the automap cache and the automap-cache count; writes at D2Client 6FACBAC6/6FACBA76 (MOV [6FBB1998],ESI / MOV [6FBB199C],ECX). | MOV DWORD PTR DS:[6FBB1998],ESI ; gpAutoMapCache / MOV DWORD PTR DS:[6FBB199C],ECX ; gnAutoMapCaches", "source": ["discord:phrozen_code msg 553938129816649728"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "1.10: gpAutoMapCache=6FBB1998, gnAutoMapCaches=6FBB199C (offsets 0x111998/0x11199C); 1.13c: 6FBCC1BC/6FBCC1B8 (0x11C1BC/0x11C1B8)"} {"id": "corpus.Charm_inventory_cell_red_blue_background_hac", "kind": "note", "status": "sourced", "trust": "sourced", "author": "Swoosh (phrozen_code Discord)", "module": "D2Client", "desc": "Patch to colour an inventory item cell's background red when a charm is not in a valid charm-zone, blue when its requirements are met. Hooks the item-cell draw path in the inventory panel; original code calls D2Common.#10244 then TEST/JE at 6FB45790. This is inventory-side-panel item rendering. | I'm trying to get charms to have a red background when not in a charm zone ... 6FB45790 E9 CB860300 JMP D2Client.6FB7DE60", "source": ["discord:phrozen_code msg 573713859219685387"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "1.13c hook site 6FB45790 (offset 0x95790); free-space patch at 6FB7DE60; JE targets 6FB457BF (red bg) / 6FB45803 (blue bg)"} {"id": "corpus.Charm_background_jump_targets_blue_red", "kind": "global", "status": "sourced", "trust": "trusted", "author": "Firehawk (phrozen_code Discord)", "module": "D2Client", "desc": "Firehawk's fixed 1.13c targets for the charm-cell background colour hack: 6FB45803 colours the inventory cell blue (reqs met), 6FB457BF colours it red (reqs not met). | D2Client.dll+0x95803 is the jump to color them blue / D2Client.dll+0x957BF is the jump to color them red", "source": ["discord:phrozen_code msg 574436785934041101"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.dll+0x95803 = jump to colour blue; D2Client.dll+0x957BF = jump to colour red (1.13c: 6FB45803 / 6FB457BF)"} {"id": "corpus.Charm_check_D2Common_ordinals_resolved_to_ad", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Firehawk (phrozen_code Discord)", "module": "D2Common/D2Client", "desc": "Ordinals used by the charm inventory-cell colouring code in 1.13c; Firehawk gives the resolved D2Client jump-stub addresses for #10744 and #11057. | #10744 - 6FABC1CC / #11057 - 6FABCA30", "source": ["discord:phrozen_code msg 574456484805476353"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "#10744 (charm itemtype check) = 6FABC1CC; #11057 (charm reqs met) = 6FABCA30; also #10244, #10840/#11057, #10756, #10731"} {"id": "corpus.Inventory_cell_hook_stack_slot_player_ptr_sh", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Firehawk (phrozen_code Discord)", "module": "D2Client", "desc": "In the charm inventory-cell draw hook the player unit pointer is at [esp+0x28] on 1.13c rather than [esp+0x20] as in 1.10 — a porting gotcha for the panel item-render stack frame. | it also seems that [esp+0x28] holds the player on 1.13c rather than [esp+0x20]", "source": ["discord:phrozen_code msg 574440581296685070"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "[esp+0x28] on 1.13c vs [esp+0x20] on 1.10"} {"id": "corpus.CLIENT_RunGame_client_app_mode_state_machine", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Full client entry point: loads LNG, UI_Init, tables, then runs the app-mode function table (nMode loop) until APPMODE_CONTINUE. APPMODE_RENDER=6 is one of the client app modes. gszInterfaces[] maps D2Client/D2Server/D2Multi/D2Launch/D2EClient. | appmode_t* pfModes = VDEF(appmode_t*,D2CLIENT,0x44EC); ... *VDEF(DWORD*,D2CLIENT,0xD44D8) = nMode;", "source": ["discord:phrozen_code msg 554750831199649792"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "gpfInterfaces table; VDEF(D2CLIENT,0x44EC) appmode fn table; gbQuitGame=D2Client+0xD4538; gdwAppMode=D2Client+0xD44D8; hInstance=+0xFA94C"} {"id": "corpus.S_C_0x58_UnitInteract_opens_UI_panel", "kind": "note", "status": "sourced", "trust": "sourced", "author": "Deleted User (phrozen_code Discord)", "module": "D2Client", "desc": "Server->client packet 0x58 opens a user-interface panel (UnitInteract); nUIType selects which UI/panel. | S>C 0x58 - Opens User Interface on Client - UnitInteract", "source": ["discord:phrozen_code msg 566896544276676638"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "sizeof 0x07: nHeader,int nUnitGUID+0x01,BYTE nUIType+0x05; conditional BP D2Client 6FAC44A1"} {"id": "corpus.CLIENT_LoadDataTables", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Common", "desc": "Client-side data-table loader; note bPrecacheTileLibraries param governs tile-library precache (floor/tile relevance). | CLIENT_LoadDataTables(D2PoolManagerStrc* pMemPool, BOOL bPrecacheTileLibraries, BOOL bCreateLvlSubList)", "source": ["discord:phrozen_code msg 586127060729331713"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Common.#10576 (1.10)"} {"id": "corpus.2D_projection_matrix_setup_OpenGL_glrenderer", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Glide/gl", "desc": "Necrolis' recipe for D2 2D rendering: glViewport(0,0,w,h); glOrtho(0,w,h,0,-1,1) with identity modelview -- top-left origin ortho matching D2 screen space. | glOrtho(0,nWidth,nHeight,0,-1,1);", "source": ["discord:phrozen_code msg 591565151413469184"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use"} {"id": "corpus.Screen_center_text_bounds_math", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Firehawk (phrozen_code Discord)", "module": "D2Client", "desc": "Belt/mouse text draw gate: computes (ScreenWidth/2)-146 and (ScreenWidth/2)-23 as x-bounds, ScreenHeight-43/-34 as y-bounds. Shows the play-area is centered via ScreenWidth/2 -- key idiom for panel/viewport offset work. | lea edx, [eax-146] ; edx = (screenwidth/2) - 146", "source": ["discord:phrozen_code msg 591715558609780737"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6CB04 (1.13d)"} {"id": "corpus.D2Gfx_DrawLine_D2Gfx_DrawRectangle", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Firehawk (phrozen_code Discord)", "module": "D2Client/D2Gfx", "desc": "Line/rect draw helpers positioned via ScreenWidth/2 - 0x90 (144) etc. DrawRectangle callable at D2Client.0xD0BA on 1.13c; D2gfx_DrawRectangle used with ScreenWidth/ScreenHeight to place a centered rect. | call D2Gfx_DrawLine -> D2Gfx_DrawRectangle", "source": ["discord:phrozen_code msg 591722401520156698"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0xD0BA (DrawRectangle, 1.13c); draw sites at D2Client 0x6CBBD/0x6CBDF, 0x6DA0A"} {"id": "corpus.D2gfx_DrawRectangle_centered_box_call", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Firehawk (phrozen_code Discord)", "module": "D2Client", "desc": "Draws a rectangle at (ScreenWidth/2 - 0x7F, ScreenHeight-0x1B) sized region -- another centered-on-play-area placement using ScreenWidth/2. | sub eax, 7Fh ... call D2gfx_DrawRectangle", "source": ["discord:phrozen_code msg 591733054247272460"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0xD0BA (1.13c); call at 0x6DA0A (1.13d)"} {"id": "corpus.UI_DrawHealthGlobe_UI_DrawManaGlobe_UI_DrawE", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Firehawk (phrozen_code Discord)", "module": "D2Client", "desc": "Bottom-panel HUD draw functions (health globe, mana globe, exp bar). | //D2Client.0x6DDE0 - UI_DrawHealthGlobe", "source": ["discord:phrozen_code msg 584829117682286592"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6DDE0 / 0x6DCA0 / 0x6CA60 (1.13d)"} {"id": "corpus.UI_DrawActiveSkillIcon_left_right_skill_pane", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Firehawk (phrozen_code Discord)", "module": "D2Client", "desc": "Draws the active skill icons in the bottom control panel. Left uses nX=0x75; right uses ScreenWidth + 0xFFFFFF5B (i.e. ScreenWidth-0xA5). bLeftSide flag distinguishes the two panels. | push 75h ; nX ... call UI_DrawActiveSkillIcon", "source": ["discord:phrozen_code msg 591727516310568991"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6EDEC (left), 0x6EE4A (right) (1.13d)"} {"id": "corpus.UI_DrawSkillIcons_UI_DrawSkillSelect", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Firehawk (phrozen_code Discord)", "module": "D2Client", "desc": "Skill-select menu draw. Right column at nX=0x50; left column at ScreenWidth + 0xFFFFFF80 (ScreenWidth-0x80). Input coords for the buttons live at 0x6F710; shifting the listed X offsets moves the popup menu too. | That's in UI_DrawSkillSelect, which is D2Client.0xA77D0", "source": ["discord:phrozen_code msg 591728187482964063"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "UI_DrawSkillSelect = D2Client.0xA77D0; skill-button input coords at D2Client.0x6F710 (1.13d)"} {"id": "corpus.GAMEUI_DrawInterface", "kind": "function", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2Client", "desc": "whist: THE entry point for in-game UI drawing -- 'the best place to start looking for ui drawing code is always there'. Takes a GameView*. Top of the panel/HUD draw tree; prime hook target for panel/play-area work. | the best place to start looking for ui drawing code is always there ... GAMEUI_DrawInterface", "source": ["discord:phrozen_code msg 594049571861168149"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0xC39E0 (1.13c/d)"} {"id": "corpus.Mini_Panel_handlers_draw", "kind": "function", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2Client", "desc": "The mini-panel (the small button strip that opens inventory/character/skill panels). Input handler table + the drawing routine at 0x64990. | The drawing code is at D2Client.0x64990", "source": ["discord:phrozen_code msg 594048880543399938"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "gptMiniPanelInputHandlers table D2Client.0xD0864; MINIPANEL_HandleInputLDown 0x64BA0; LUp 0x662E0; drawing code D2Client.0x64990"} {"id": "corpus.UI_background_color_handler", "kind": "global", "status": "sourced", "trust": "sourced", "author": "Szumigajowy (phrozen_code Discord)", "module": "D2Client", "desc": "Szumigajowy: this address 'handle background color' -- candidate for the panel/dead-zone background fill. | D2Client.0x6FAE1710 handle background color", "source": ["discord:phrozen_code msg 599300804926767109"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FAE1710"} {"id": "corpus.Item_slot_color_rect_draw_sites_D2DrawRect", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Necrolis: to color item background rects you must patch many D2DrawRect call sites -- belt, inv slots, equipment slots, merc, vendors -- because coloring wasn't done in the item draw function. Enumerates the 1.10 panel item-slot draw calls. | belt drawing, inv slots, equipment slots, merc, vendors etc, this amounts to quite a few calls to D2DrawRect", "source": ["discord:phrozen_code msg 606433982195957790"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "1.10 D2Client: 0x6FAE026E,0352,04BD,05DF,0EE9,1116,12BA,ED999,0x6FB0064D,B254C6,B57B93"} {"id": "struct.Act_RoomCoords", "kind": "struct", "status": "sourced", "trust": "sourced", "author": "Thaison (phrozen_code Discord)", "module": "D2Common", "desc": "Act: pEnviroment+0x04, nTownLevel+0x08, dwMapSeed+0x0C, pRoom1+0x10, TileData+0x18, ActMisc*+0x48, pMemoryPool+0x5C. RoomCoords (Room1+0x4C, 0x20 bytes): dwXStart/YStart/XSize/YSize, wTileX+0x10, wTileY+0x14, dwTilesWidth+0x18, dwTilesHeight+0x1C -- tile origin/extent of a room. | struct RoomCoords // sizeof(0x20) 32 bytes of Room1+4C", "source": ["discord:phrozen_code msg 606065792433258502"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use"} {"id": "struct.ActEnvironment", "kind": "struct", "status": "sourced", "trust": "sourced", "author": "Thaison (phrozen_code Discord)", "module": "D2Common", "desc": "Day/night lighting env: nTimeIndex, nDaytime, nIntensity+0x0C, nRed/nGreen/nBlue +0x18-0x1A, fCos/fLast/fSin +0x1C-0x24, dwTimeRate+0x28, bEclipse+0x30. Drives the outdoor floor/ambient light color. | struct ActEnvironment // sizeof(0x38)", "source": ["discord:phrozen_code msg 606066148513153044"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "Act+0x04, sizeof 0x38"} {"id": "struct.TileData", "kind": "struct", "status": "sourced", "trust": "sourced", "author": "Thaison (phrozen_code Discord)", "module": "D2Common", "desc": "Tile placement record: nWidth/nXposEx+00, nHeight/nYposEx+04, nXpos+08, nYpos+0C, fFlags+14, D2TileLibraryEntryStrc* pTile+18, nRed/nGreen/nBlue/nIntensity +0x28-0x2B. Per-tile screen position + tint for floor rendering. | struct TileData //sizeof 0x30", "source": ["discord:phrozen_code msg 606066796759351309"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "Act+0x18, sizeof 0x30"} {"id": "struct.D2TileLibraryEntryStrc", "kind": "struct", "status": "sourced", "trust": "sourced", "author": "Nightshades (phrozen_code Discord)", "module": "D2Common", "desc": "Tile library entry; DT1 filename pointer at offset 0x58 (88 dwords in). | char* szDT1FileName; //0x058", "source": ["discord:phrozen_code msg 606067216760438784"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "szDT1FileName at +0x058"} {"id": "corpus.DRLG_grid_cell_lookup_sub_6FD75CA0_DRLGGrid_", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Mnw1995 / Lectem (phrozen_code Discord)", "module": "D2Common", "desc": "Cell lookup: pCellPos[nCellPosId + pCellFlags[nCellFlagId]]. DRLGGrid = {int* pCellPos, int* pCellFlags, nWidth(nCells), nHeight, nullOnInit}; Lectem's D2DrlgCoordIndexStrc variant has pIndexList checked via bitmasks. drlg tile flags at D2DrlgTileDataStrc+0x14. | return pDrlgGrid->pCellPos[nCellPosId + pDrlgGrid->pCellFlags[nCellFlagId]];", "source": ["discord:phrozen_code msg 612593538592407562"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Common.0x6FD75CA0 (1.10f)"} {"id": "corpus.UI_DrawSkillSelect_skill_button_input_coords", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Firehawk (phrozen_code Discord)", "module": "D2Client", "desc": "Where the majority of input coordinates for the skill-button inputs live; shifting the X offsets also moves the skill-select popup that appears. | D2Client.0x6F710 is where the majority of the input coordinates for the skill button inputs are on 1.13d", "source": ["discord:phrozen_code msg 591730701414563890"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6F710 (1.13d)"} {"id": "corpus.D2Win_widgets_vs_bank_dialog", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Win", "desc": "UI widget structs (editbox etc.) come from D2Win and are cleanly done; the arg-1 object at D2Client 6FAD7540 (1.10f) is the ad-hoc bank dialog code which is messy and reused by other adhoc menus - advise side-stepping. | The widgets come from D2Win, these are actually properly done... What you are refering to in that code is the incredible piece of shit that is the ban", "source": ["discord:phrozen_code msg 625620363711217674"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client 6FAD7540 (1.10f)"} {"id": "corpus.world_screen_coordinate_conversion", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Common/D2Client", "desc": "KEY RENDER FACT: world<->screen conversion done by D2Common ordinals in the #1011x range (choose tile vs subtile variant), result then offset by the CURRENT SCREEN WORLD CENTER (camera). This is the camera/scroll offset applied to drawn units/tiles. | Conversion is done via a few funcs in the D2Common.#1011x range depending on if you want tile or subtile coords, and then offset by the current screen", "source": ["discord:phrozen_code msg 653371790663352342"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Common.#1011x range"} {"id": "corpus.D2PreLoadImages", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Deleted User (phrozen_code Discord)", "module": "D2Client", "desc": "Client image preload routine at 0x5E370 + ClientOffset. | D2PreLoadImages = (0x5E370 + ClientOffset); // D2Client.6FAFE370", "source": ["discord:phrozen_code msg 653988779815600138"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.6FAFE370 (offset 0x5E370)"} {"id": "corpus.ALT_item_popup_draw_routines", "kind": "global", "status": "sourced", "trust": "sourced", "author": "Szumigajowy (phrozen_code Discord)", "module": "D2Client", "desc": "Ground-item name popups (shown while ALT held) are driven from d2client.6FB21B70; the actual popup draw is at 0x6FB09F60. | How the hell game does draw item popups when pressing alt? ... 0x6FB09F60", "source": ["discord:phrozen_code msg 656673105774903308"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "d2client.6FB21B70 / 0x6FB09F60"} {"id": "corpus.UNITDRAW_DrawUnit", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "CORE RENDER: __fastcall(pUnit,dwColorTint,nXpos,nYpos,bFade,bDrawOverlays) - draws a unit's sprite at screen X/Y with tint/fade/overlays. This is the per-unit draw entry in the play-area render path. | Function: UNITDRAW_DrawUnit Address: D2Client.0x6FB5A720", "source": ["discord:phrozen_code msg 657275575668310066"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FB5A720"} {"id": "corpus.UNITDRAW_CacheGFXData", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "RENDER: __forceinline __fastcall(pGFXData,pUnit,pCellFile,nDirection,nFrame,fFlags,dwColorTint,pIndex) - caches the cell/DCC gfx data for a unit before drawing; called from UNITDRAW_DrawUnit. | Function: UNITDRAW_CacheGFXData Address: D2Client.0x6FB5EC80", "source": ["discord:phrozen_code msg 657275860729987093"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FB5EC80"} {"id": "corpus.inventory_input_handler", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Thaison (phrozen_code Discord)", "module": "D2Game", "desc": "Inventory action handler sig (Game* pGame, Inventory* pInv, int nInput, int* a5, int* a6); a5/a6 last two args undetermined. | (Game* pGame, Inventory* pInv, int nInput, int* a5, int* a6)", "source": ["discord:phrozen_code msg 666284062339760158"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "[1.10f] 6FC8F450 / [1.13c] 6FC90240"} {"id": "corpus.HUD_close_menu_click_coordinate_1_10", "kind": "global", "status": "sourced", "trust": "sourced", "author": "Conqueror (phrozen_code Discord)", "module": "D2Client", "desc": "1.10 address near 6FB0124D controls X,Y of the click on the HUD rectangle; modifying byte 75 to 0FF with a JMP changes menu-close coords. Render/HUD-layout relevant. | for 1.10 it is near to 6FB0124D because modifying those values slightly modifies me ... to make the HUD more elegant", "source": ["discord:phrozen_code msg 678042800004136961"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FB0124D (1.10)"} {"id": "corpus.UI_GetState_D2CLIENT_gnUiToggle", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Szumigajowy (phrozen_code Discord)", "module": "D2Client", "desc": "UI panel open/close state reader: BOOL __fastcall UI_GetState(int nUiIndex) at D2Client.0x6FB23230 (1.10f); reads global array D2CLIENT_gnUiToggle[nUiIndex]; UITOGGLE_ESCMENU=9, bounded by NUM_UI. Core of knowing which side panels are open. | Address: D2Client.0x6FB23230 ... return D2CLIENT_gnUiToggle[nUiIndex];", "source": ["discord:phrozen_code msg 678173049237012481"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FB23230 (1.10f)"} {"id": "corpus.D2Client_0x521C0_string_desc_builder", "kind": "global", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "D2Client.0x521C0 builds the item/stat string descriptions; entry point to find the desc-generation function. | D2Client.0x521C0 builds the string descs, you can find the func from there", "source": ["discord:phrozen_code msg 684051873829093397"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x521C0"} {"id": "corpus.merc_items_draw_global_dword_6FBCBE5C", "kind": "note", "status": "sourced", "trust": "sourced", "author": "misiek1294 (phrozen_code Discord)", "module": "D2Client", "desc": "Global dword_6FBCBE5C (1.13c) / dword_6FBB5B14 (1.10) used as a loop counter inside the mercenary-items draw function; observed always 0. | I found that inside merc items draw functions (compare loop counter with that but this is always 0 )", "source": ["discord:phrozen_code msg 685515561207463968"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "dword_6FBCBE5C (1.13c) / dword_6FBB5B14 (1.10)"} {"id": "corpus.D2GetItemName_D2Client_6FAD7210", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "D2Client.6FAD7210 = D2GetItemName(pItem, wszBuffer, nBufferSize); called from 5 sites (6FADBBD6/6FADC43D/6FADC9B5/6FADD488/6FADD90D) — the item-description name builders, hookable to inject extra tooltip lines. | CALL D2Client.6FAD7210 ; D2GetItemName(D2UnitStrc* pItem, wchar_t* wszBuffer, size_t nBufferSize)", "source": ["discord:phrozen_code msg 693904743902478347"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.6FAD7210"} {"id": "corpus.D2CLIENT_ItemLevel_tooltip_hook_offsets", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Kieran/Harvest (phrozen_code Discord)", "module": "D2Client", "desc": "Item-Level-on-tooltip hook: patch site file offset 0x438A1 (1.9-1.13 variants 3D47C/438A1/ADD0A/789DA/AE0AA/941C0); 1.13 live 0x6FB341C0-... ; Set-item variant patch at 0x427BE. Uses D2CLIENT_SetColourPopUp (D2SetColorPopup, D2Client 85A60 in 1.11). | {D2DLL_D2CLIENT, 0x438A1, PATCH_CALL, FALSE, 1}, //6FAE38A1", "source": ["discord:phrozen_code msg 693902883057565716"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "0x438A1 / 0x427BE / 0x941C0 (1.13)"} {"id": "corpus.SPEEDBOOK_DrawMenu", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Skill speed-book (radial skill selector) draw routine: void __fastcall SPEEDBOOK_DrawMenu(int nStart, BOOL bLeft, BOOL bDesc) at D2Client.0x6FB19720. On-screen HUD panel render. | Function: SPEEDBOOK_DrawMenu\n Address: D2Client.0x6FB19720", "source": ["discord:phrozen_code msg 695486882716582028"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FB19720"} {"id": "corpus.SPEEDBOOK_ClickDown", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Speed-book click handler: void __stdcall SPEEDBOOK_ClickDown(D2WinMsgStrc* pMsg) at D2Client.0x6FB19BB0. | Function: SPEEDBOOK_ClickDown\n Address: D2Client.0x6FB19BB0", "source": ["discord:phrozen_code msg 695486932926595092"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FB19BB0"} {"id": "corpus.SPEEDBOOK_DrawIconEx", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Speed-book skill-icon draw: void __fastcall SPEEDBOOK_DrawIconEx(D2CellFileStrc* pCells, D2SkillStrc* pSkill, SkillsTXT* pRecord, DWORD dwGUID, int nValue, int nColor, int nXpos, int nYpos, BOOL bLeft) at D2Client.0x6FB18AC0. Takes explicit X/Y screen coords. | Function: SPEEDBOOK_DrawIconEx\n Address: D2Client.0x6FB18AC0", "source": ["discord:phrozen_code msg 695486979948675072"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FB18AC0"} {"id": "corpus.SKILLTREE_DrawTabIcons", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Skill-tree panel tab-icon draw: void __fastcall SKILLTREE_DrawTabIcons(D2UnitStrc* pPlayer, int nTab, int nClass) at D2Client.0x6FB163B0 and 0x6FB16A50 (two entry points). Left-side skill panel render. | Function: SKILLTREE_DrawTabIcons\n Address: D2Client.0x6FB163B0 & D2Client.0x6FB16A50", "source": ["discord:phrozen_code msg 695487080897314877"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FB163B0 & 0x6FB16A50"} {"id": "corpus.SKILLTREE_ClickDown_SKILLTREE_ClickUp", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Skill-tree panel mouse handlers: SKILLTREE_ClickDown at D2Client.0x6FB17A80 and SKILLTREE_ClickUp at D2Client.0x6FB18100, both __stdcall(D2WinMsgStrc*). | Function: SKILLTREE_ClickDown\n Address: D2Client.0x6FB17A80", "source": ["discord:phrozen_code msg 695487239894990931"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FB17A80 / 0x6FB18100"} {"id": "struct.itemData_invPage_INVPAGE_INVENTORY_CUBE_STAS", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2Common", "desc": "Item location is read from itemData->invPage compared against INVPAGE_INVENTORY / INVPAGE_CUBE / INVPAGE_STASH to distinguish inventory vs cube vs stash. Panel-context test. | return itemData->invPage == INVPAGE_STASH;", "source": ["discord:phrozen_code msg 698768576772833300"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "itemData->invPage"} {"id": "corpus.HelloWorld_RevealMinimap_hook_interaction_bu", "kind": "note", "status": "sourced", "trust": "sourced", "author": "Ownasaurus (phrozen_code Discord)", "module": "D2Client", "desc": "Practical note: a draw-text hook and a reveal-minimap hook each work alone in DLL_PROCESS_ATTACH, but running back-to-back the minimap reveal fails — timing/ordering caveat when hooking D2 draw functions at attach. | when executed back-to-back like here, the minimap is not revealed", "source": ["discord:phrozen_code msg 701930851277209682"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "DLL_PROCESS_ATTACH"} {"id": "struct.D2RendererFunctionsStrc", "kind": "struct", "status": "sourced", "trust": "sourced", "author": "dzik (phrozen_code Discord)", "module": "D2gfx/renderer", "desc": "Full vtable of the swappable renderer backend (GDI/DirectDraw/Glide/D3D). D2 swaps this table on init depending on selected renderer. Includes fpBeginScene, fpEndScene, fpFlipBufferProbably, fpGetBackBuffer, fpGetScreenSize, fpUpdateScaleFactor, fpSetPerspectiveScale, fpAdjustPerspectivePosition, fpPerspectiveScalePosition, fpSetDefaultPerspectiveFactor, fpSetPalette, fpSetGlobalLight, fpDrawRect/RectEx, fpDrawSolidR | I am trying to figure out what are those undefined functions for each of renderer modes ... D2 swap table upon initialization depending on selected re", "source": ["discord:phrozen_code msg 727223450904559707"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "vtable offsets 0x0..0xd0 (fpBeginScene=+0x18, fpGetScreenSize=+0x50, fpSetPerspectiveScale=+0x60, fpDrawRect region ~+0xa8)"} {"id": "corpus.gpMapGfxCells_map_name_table_patches", "kind": "global", "status": "sourced", "trust": "trusted", "author": "Kingpin (phrozen_code Discord)", "module": "D2Common / D2Game", "desc": "Patch sites that repoint D2Common map graphics cell lookups (nFirst/nLast) and map-name-size table into a custom gpMapGfxCells / gpfMapNamesSize array. Involves floor/level tile graphics cell indexing: base formula (ID*4)+(GameOffset+0xFF018), original ref 6FC6F5E6. | (DWORD)&gpMapGfxCells[0].nFirst; // 6FC6F5E6 (ID * 4) + (GameOffset + 0xFF018)", "source": ["discord:phrozen_code msg 710553646789820447"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "CommonOffset+0x22C7F/0x22D46 (nFirst), +0x22C4E/0x22C9F/0x22D4D (nLast), +0x22AF5/+0x22B32 (map names); orig 6FC6F5E6; GameOffset+0xFF018"} {"id": "corpus.GetUnitX_GetUnitY_subtile_position", "kind": "global", "status": "sourced", "trust": "sourced", "author": "Arolds (phrozen_code Discord)", "module": "D2Client", "desc": "D2Client exports giving a unit's subtile X/Y position; also discussion of obtaining the 'world view subtile' (where the character stands / camera anchor). Relevant to screen-to-world mapping and viewport offset. | the ones I can get with 1.13c d2client.dll +0x1630 and +0x1660 ... how do I get the world view subtile? Is that where my character stands?", "source": ["discord:phrozen_code msg 727259770481934397"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.dll +0x1630 (GetUnitX), +0x1660 (GetUnitY)"} {"id": "struct.DrlgLevel_LevelPreset_offset", "kind": "struct", "status": "sourced", "trust": "sourced", "author": "Thaison (phrozen_code Discord)", "module": "D2Common", "desc": "DrlgLevel+0x1CC (1.13c) / +0x21C (1.10) points to the LevelPreset structure {dwDef, dwFiles, dwPreset, pNext*}. Level/DRLG generation data. | [1.13c] DrlgLevel + 0x1CC [1.10] DrlgLevel + 0x21C ... struct LevelPreset", "source": ["discord:phrozen_code msg 717717740361744384"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "DrlgLevel+0x1CC (1.13c) / +0x21C (1.10)"} {"id": "corpus.Barkscroll_UI_custom_draw_hook", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Mini-guide to inject a custom UI: hook client-side item right-click handler (find barkscroll item code in D2Client), set a global, open barkscroll UI; hook the barkscroll draw function to load/draw a replacement DC6 when the global is set. A concrete example of hooking a D2Client panel draw routine. | Hook barkscroll draw function, if that global is set, load (and unload the old DC6) and then draw the new DC6", "source": ["discord:phrozen_code msg 719282164314931241"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client barkscroll item/draw handlers (not addressed)"} {"id": "struct.D2AutoMapRecordStrc_gpMapGfxCells", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "Kingpin (phrozen_code Discord)", "module": "D2Common", "desc": "Automap cell-range record {int nFirst;+00, int nLast;+04} indexed per level-type; gpMapGfxCells[MAX_LEVELTYPES] gives first/last automap gfx cell for each of the 45 level types (full name table listed). Automap/render data | struct D2AutoMapRecordStrc { int nFirst; //+00 int nLast; //+04 };", "source": ["discord:phrozen_code msg 742334329149063169"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use"} {"id": "corpus.automap_gfx_cell_mapname_table_relocation_of", "kind": "global", "status": "sourced", "trust": "trusted", "author": "Kingpin (phrozen_code Discord)", "module": "D2Common", "desc": "D2Common code sites patched to repoint automap cell lookup to a custom gpMapGfxCells array: CommonOffset +0x22C7F/0x22D46 (nFirst), +0x22C4E/0x22C9F/0x22D4D (nLast); +0x22AF5/0x22B32 for map-name strings. Original formula (ID*4)+(GameOffset+0xFF018), asm 6FC6F5E6 | 6FC6F5E6 (ID * 4) + (GameOffset + 0xFF018)", "source": ["discord:phrozen_code msg 742334501371248664"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "CommonOffset+0x22C4E..0x22D4D"} {"id": "corpus.gold_drop_dialog_UI_functions_1_13c", "kind": "global", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2Client", "desc": "whist's UI notes: input handlers (14) at D2Client.0xDE858; draw the gold drop dialog at D2Client.0xA3840; open-dialog function D2Client.0xC30E0; in-memory dialog struct D2Client.0xFAD60. Panel drawing/UI | draw the gold drop dialog: D2Client.0xA3840", "source": ["discord:phrozen_code msg 754042765196656782"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "draw=0xA3840, open=0xC30E0, struct=0xFAD60, input=0xDE858"} {"id": "corpus.D2gfx_flush_window_function_18F46_flag", "kind": "global", "status": "sourced", "trust": "sourced", "author": "Kieran (phrozen_code Discord)", "module": "D2gfx", "desc": "D2gfx 6FA748C0 calls #10004 then 6FA7BCEE; 6FA7BCEE reads [esp+8], on TEST EAX zeroes ecx, writes result to [eax+0x18F46] (a D2gfx window/state flag). Kieran patch subject, Necrolis gave clean naked stub | 6FA748C5 E8 24740000 CALL D2gfx.6FA7BCEE", "source": ["discord:phrozen_code msg 758305609367420948"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2gfx.6FA748C0 / 6FA7BCEE; [eax+0x18F46]"} {"id": "corpus.D2Cmp_ordinal_10044_1_10_10067_1_13c", "kind": "note", "status": "sourced", "trust": "sourced", "author": "misiek1294 (phrozen_code Discord)", "module": "D2Cmp", "desc": "Cross-version ordinal mapping in D2Cmp (graphics/cell decompression module): #10044 in 1.10 == #10067 in 1.13c | D2Cmp.10044 (1.10) D2Cmp.10067(1.13c)", "source": ["discord:phrozen_code msg 770376168443740250"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Cmp #10044/#10067"} {"id": "corpus.Display_Text_D2Win_10171", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Silvermane (phrozen_code Discord)", "module": "D2Win/D2Client", "desc": "Draws a Unicode string: ECX=ptr to unicode string, EDX=x, Arg1=y, Arg2=colour, Arg3=always 0. Called from D2Client to print stats on character screen. | Function: Display Text Address: 6F8AAD40 in v1.10 ECX - pointer to Unicode String EDX - x coord Arg1 - y coord Arg2 - colour", "source": ["discord:phrozen_code msg 780155845118918696"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6F8AAD40 (v1.10)"} {"id": "corpus.Area_Level_print_asm_level_name_overlay", "kind": "note", "status": "sourced", "trust": "sourced", "author": "Silvermane (phrozen_code Discord)", "module": "D2Client", "desc": "Silvermane's on-screen text overlay: calls level-name printout at D2Client.6FACF0D0, fetches Y coord from [6FBB19FC] and X coord from [6FB9A704], SUB EDX,30 to shift X, then D2Win #10171 display text. Shows the screen coord globals used for HUD text placement. | MOV EAX,DWORD PTR DS:[6FBB19FC] ; retrieve Y coordinate ... MOV EDX,DWORD PTR DS:[6FB9A704] ; retrieve X coordinate SUB EDX,30", "source": ["discord:phrozen_code msg 780155973700550657"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FB6C534 CALL D2Client.6FACF0D0"} {"id": "corpus.Charm_inventory_location_check_1_13c", "kind": "note", "status": "sourced", "trust": "sourced", "author": "Canight (phrozen_code Discord)", "module": "D2Common", "desc": "Patch point in inventory placement: CheckCharmInvLocation(pItem) validates a charm's inventory location (ItemLocation, IsMatchingType 0x0D, pItemPath->dwPosY>3). Directly touches inventory-panel item placement logic. | // Charm Inventory check {D2DLL_D2COMMON, 0x27064, PATCH_JMP...} ... if (pItemPath->dwPosY > 3) return TRUE;", "source": ["discord:phrozen_code msg 781257646861713419"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Common 0x27064/0x27065"} {"id": "corpus.Get_the_Node_Page_item_container_page", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Silvermane (phrozen_code Discord)", "module": "D2Common", "desc": "Returns which container/page an item is in: 00 Inventory, 01 BodyLoc, 02 Belt, 03 Ground, 04 Cursor. Core mapping for inventory/equip side-panel item location. | Get the Node Page Offset: 00052100 (6FD92100) ... 00: Inventory 01: BodyLoc 02: Belt 03: Ground 04: Cursor", "source": ["discord:phrozen_code msg 781962398227628082"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "00052100 (6FD92100) v1.10"} {"id": "corpus.D2FillArea_underlying_renderer_call", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Deleted User (phrozen_code Discord)", "module": "D2Gdi/Game", "desc": "D2FillArea passes 6 params; in 1.13d the CALL EAX lands in D2Gdi 0x6f877370 (takes all 6), in 1.14d lands at 0x006c8a60 windowed renderer (uses only params 3-6). Area-fill (solid rect) render path. | in 13d the CALL goes to this address 0x6f877370 in D2Gdi.dll that function takes all 6 paramters from D2FillArea", "source": ["discord:phrozen_code msg 790238831760375829"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "1.13d D2Gdi.dll 0x6f877370; 1.14d 0x006c8a60"} {"id": "corpus.D2GFX_DrawSolidRectEx", "kind": "function", "status": "sourced", "trust": "sourced", "author": "dzik (phrozen_code Discord)", "module": "Game (1.14)", "desc": "void(nXStart,nYStart,nXEnd,nYEnd,dwColor,nDrawMode) - wrapper to every renderer. Guards x<=xEnd && y<=yEnd then calls [DAT_007c8cc0+0xB8](xEnd,yEnd,color,mode). This is the solid-rectangle fill primitive (relevant to dead-zone/panel-area fills). | void D2GFX_DrawSolidRectEx(int nXStart,int nYStart,int nXEnd,int nYEnd,DWORD dwColor,int nDrawMode)", "source": ["discord:phrozen_code msg 790273809327587368"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "0x4f6300"} {"id": "corpus.RENDERER_WINDOWED_DrawSolidRectEx", "kind": "function", "status": "sourced", "trust": "sourced", "author": "dzik (phrozen_code Discord)", "module": "Game (1.14)", "desc": "Windowed-mode renderer solid-rect fill; __fastcall(x1,y1,x2,y2,byte color,int mode). The concrete windowed backend behind D2GFX_DrawSolidRectEx wrapper (0x4f6300). | //0x6c8a60 void __fastcall RENDERER_WINDOWED_DrawSolidRectEx (uint param_1,uint param_2,...)", "source": ["discord:phrozen_code msg 790276327026196490"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "0x6c8a60"} {"id": "corpus.resolution_mode_global_1_14d", "kind": "global", "status": "sourced", "trust": "sourced", "author": "dzik (phrozen_code Discord)", "module": "Game (1.14)", "desc": "Resolution mode stored at 0x7c8cb8; the renderer object base DAT_007c8cc0 has draw funcs at +0xB8. Directly governs play-area sizing / resolution. | resolution mode in 1.14d is stored here 0x7c8cb8", "source": ["discord:phrozen_code msg 790284584126119956"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "0x7c8cb8 (also renderer vtable base DAT_007c8cc0)"} {"id": "corpus.D2Client_viewport_camera_globals_1_13c_relat", "kind": "global", "status": "sourced", "trust": "sourced", "author": "Deleted User (phrozen_code Discord)", "module": "D2Client", "desc": "Deleted User's D2Client global-offset table: resolution X/Y and the WINDOW START X / negative window-start Y offsets = the play-area origin / screen-shift/camera-offset globals. Highly relevant to viewport positioning beside panels. | ptNegWindowStartY = (DWORD*)(offset_D2Client + 0x3A285C); ptWindowStartX = (DWORD*)(offset_D2Client + 0x3A2858);", "source": ["discord:phrozen_code msg 790289346980216832"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "ResY +0x311470, ResX +0x31146C, NegWindowStartY +0x3A285C, WindowStartX +0x3A2858, IsLodGame +0x3A04F4, MouseY +0x3A6AAC, MouseX +0x3A6AB0, ptClientChar +0x3A6A70"} {"id": "corpus.D2isLODGame_D2GetDifficultyLevel_D2GetMouseX", "kind": "function", "status": "sourced", "trust": "sourced", "author": "dzik (phrozen_code Discord)", "module": "D2Client (1.14 merged Game.exe)", "desc": "1.14 (post-DLL-merge) addresses; note subtract 0x400000 to get RVA. Mouse X/Y getters useful for cursor-vs-viewport mapping. | D2GetMouseX ... -> 0x468730 ... D2GetMouseY ... -> 0x468740", "source": ["discord:phrozen_code msg 790288274568380460"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "isLOD 0x44dcc0, GetDifficulty 0x44dcd0, GetMouseX 0x468730, GetMouseY 0x468740"} {"id": "corpus.D2Win_D2DrawText_10117", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Silvermane (phrozen_code Discord)", "module": "D2Win", "desc": "void __fastcall(wchar_t* pString,int nXpos,int nYpos,int nColour,int nTransTbl). Main HUD unicode draw call. | D2FUNC(D2WIN, D2DrawText, void, __fastcall, (wchar_t* pString, int nXpos, int nYpos, int nColour, int nTransTbl), 0xAD40)", "source": ["discord:phrozen_code msg 790720784418209832"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "0xAD40"} {"id": "struct.D2GFXCelStrc", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2gfx/cel", "desc": "Cel graphic header: +00 bFlip, +04 nWidth, +08 nHeight, +0C nXOffset, +10 nYOffset, +14 dwNodeLength, +18 pCelNode (also offset to next cel in file), +1C dwLength, +20 pPixels[]. Core sprite/floor-tile blit struct. | struct D2GFXCelStrc //sizeof 0x20 + x { BOOL bFlip; //+00 int nWidth; //+04 ... uint8_t pPixels[]; //+20 };", "source": ["discord:phrozen_code msg 789293075193135145"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "sizeof 0x20 + pixels"} {"id": "corpus.D2SetScrollEndFunc_sets_two_scroll_end_callb", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Kingpin (phrozen_code Discord)", "module": "D2Client", "desc": "void __fastcall(func1,func2) that initializes two function-pointer globals. Kingpin named it D2SetScrollEndFunc. Named for scroll-end handling (viewport scroll callbacks). | static D2Client6FB1CBD0 D2SetScrollEndFunc = (D2Client6FB1CBD0)(0x7CBD0 + ClientOffset); // D2Client.6FB1CBD0", "source": ["discord:phrozen_code msg 795638548438581258"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FB1CBD0 (RVA 0x7CBD0); globals 6FBB9F58/6FBB9F5C (1.10), 6FBCBF94/6FBCBF98 (1.13c)"} {"id": "struct.DRLGLevelStruct_Level", "kind": "struct", "status": "sourced", "trust": "sourced", "author": "Thaison (phrozen_code Discord)", "module": "D2Common", "desc": "Full DRLG Level struct layout: dwDrlgType@0x00 (1 maze,2 preset,3 wilderness), pRoom2First@0x10, union maze/preset/wilderness@0x14, dwPosX@0x1C, dwPosY@0x20, dwSizeX@0x24, dwSizeY@0x28, pNextLevel@0x1AC, pMisc@0x1B4, dwLevelType@0x1C0, hSeed@0x1C4, pLevelPresets@0x1CC, dwLevelNo@0x1D0, RoomCenterX/WarpX[9]@0x1E0, RoomCenterY/WarpY[9]@0x204, dwRoomEntries@0x228. Crash in D2Common #10322 DRLGInitLevel tied to sizeX/siz | DWORD dwDrlgType; //0x00 1 - maze, 2 - preset, 3 - wilderness ... DWORD dwSizeX; //0x24 DWORD dwSizeY; //0x28", "source": ["discord:phrozen_code msg 797299453752246303"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "+0x00..+0x22C; DRLGInitLevel #10322"} {"id": "corpus.Skill_icon_drawing_function", "kind": "function", "status": "sourced", "trust": "trusted", "author": "kain_abel_666 (quoting Necrolis) (phrozen_code Discord)", "module": "D2Client", "desc": "Function responsible for drawing the skill icons in 1.10 | In 1.10 have a look at D2Client.0x6FB18AC0, its responsible for drawing the icons.", "source": ["discord:phrozen_code msg 800001848672387082"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FB18AC0 (1.10)"} {"id": "corpus.ExpDrawLine_via_D2GFX_10057", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2GFX", "desc": "Hookable draw-line export; params (nXStart,nYStart,nXEnd,nYEnd,nPaletteIndex,nAlpha); width = end-start. Direct hook point for line rendering | void __stdcall ExpDrawLine(int nXStart, int nYStart, int nXEnd, int nYEnd, uint8_t nPaletteIndex, uint8_t nAlpha)", "source": ["discord:phrozen_code msg 807990340560093225"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2GFX.#10057"} {"id": "corpus.CDraw_Game_UI", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Silvermane (phrozen_code Discord)", "module": "D2Client", "desc": "Core game-UI draw function; hook target for drawing UI (calls #10072). Called from within larger UI routine; also builds a 0x13C stack frame at 6FB21B70 | //D2Client.6FB20A30 D2FUNC(D2CLIENT, CDraw_Game_UI, void, __fastcall, (DWORD Arg01), 0x80A30)", "source": ["discord:phrozen_code msg 808361786982006804"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.6FB20A30 / +0x80A30"} {"id": "corpus.GUI_stat_skill_button_draw_calls", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Inside the GUI draw routine: CALL 6FAEF360 draws stat-points buttons, CALL 6FAEF730 draws skill-points buttons (at 6FB22030/6FB22044) | CALL d2client.6FAEF360 ; GUI Buttons -> stat points ... CALL d2client.6FAEF730 ; GUI Buttons -> skillpts", "source": ["discord:phrozen_code msg 808388900963090483"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FB22030->6FAEF360, 6FB22044->6FAEF730"} {"id": "corpus.Panel_Level_DC6_side_panel_graphics", "kind": "note", "status": "sourced", "trust": "trusted", "author": "kain_abel_666 / Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "The 'Panel\\Level' DC6 (character/level side panel gfx) string is at D2Client.6FB79AB0; loaded via DC6 load function D2Client.6FB20100 and the loaded handle stored at global [6FBB5BB4]; corresponding unload function at D2Client.6FB20140. Load MOV ECX,6FB79AB0 at 6FAEEBA0; store MOV [6FBB5BB4],EAX at 6FAEEBAF | 6FAEEBA0 MOV ECX,D2Client.6FB79AB0 ; ASCII \"Panel\\Level\" ... so DC6/DCC loading function is D2Client.6FB20100?", "source": ["discord:phrozen_code msg 808879441106173962"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "str 6FB79AB0; load 6FB20100; unload 6FB20140; global 6FBB5BB4"} {"id": "corpus.Ctrl_click_drop_item_refresh_chain", "kind": "note", "status": "sourced", "trust": "sourced", "author": "Silvermane (phrozen_code Discord)", "module": "D2Common/D2Game", "desc": "Correct sequence to drop from inventory without leaving blank slot: ChangeAnimMode(IMODE_ONGROUND), RemoveItemFromInventory, GetRoom, D2DropItem(pGame,NULL,pItem,pRoom,x,y), then server UpdateInventoryItems + RefreshInventory | D2COMMON_INVENTORY_RemoveItemFromInventory(pUnit->pInventory, pItem); D2GAME_D2DropItem(pGame, NULL, pItem, pRoom, pCoords.nX, pCoords.nY);", "source": ["discord:phrozen_code msg 806619543932764181"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "UpdateInventoryItems / RefreshInventory"} {"id": "corpus.Automap_level_type_table_extension_1_13c", "kind": "note", "status": "sourced", "trust": "sourced", "author": "Mubbsy (phrozen_code Discord)", "module": "D2Common", "desc": "Automap uses hardcoded ASCII level-type table in D2Common .rdata; table start at 6FDDB9E0 (offset 0xB9E0), sole reference/call at offset 0x6B30D (live 6FDBC30D) which loads table into EDI. To extend past lvltype 35 relocate table and repoint the call | copies the table from 6FDDB9E0 into the EDI register ... the call to that address at 0x6B30D", "source": ["discord:phrozen_code msg 814006465484161054"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "table 6FDDB9E0 (0xB9E0); ref 0x6B30D (6FDBC30D)"} {"id": "struct.D2AutoMapRecordStrc_gpfMapNamesSize", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "Kingpin (phrozen_code Discord)", "module": "D2Common", "desc": "Automap record {int nFirst;+00, int nLast;+04}; MAX_LEVELTYPES 255; level-type name table gpfMapNamesSize[] (0=None..35 '5 Lava', 36+ Dark Alliance/dummy). Patch points to repoint gpMapGfxCells and name table at D2Common +0x22C7F/22D46 (nFirst), +0x22C4E/22C9F/22D4D (nLast), +0x22AF5/22B32 (names) | struct D2AutoMapRecordStrc { int nFirst; //+00 int nLast; //+04 };", "source": ["discord:phrozen_code msg 814023302238044190"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "CommonOffset +0x22AF5/+0x22C4E/+0x22C7F/+0x22C9F/+0x22D46/+0x22D4D"} {"id": "corpus.Automap_txt_lvltypes_txt_dynamic_link_Automa", "kind": "note", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2Common", "desc": "whist's extension: rebuilt automap.txt compile to link LevelName to lvltypes.txt (TXTLINKER_LVLTYPES) so table can be arbitrary size (256+ pairs). AutomapBin record layout: TileName@0x10, Style@0x18, Start/EndSequence@0x19/0x1A, Cel1-4@0x1C/0x20/0x24/0x28. Patch stubs at D2Common 0x6CEF4 (GetLvlTypeFromAutomapRecord), 0x6CE9B (CompileAutomapTables), plus range-table repoints at 0x6CFF3/0x6FAD4/0x6CFB0/0x6D013/0x6FADF | {\"TileName\", TXTFIELD_ASCII, 7, 0x10, 0} ... {\"Cel1\", TXTFIELD_DWORD, 0, 0x1C, 0}", "source": ["discord:phrozen_code msg 814059154461294642"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Common +0x6CEF4/0x6CE9B/0x6CFF3/0x6CFB0/0x6D013/0x6CFD1; record +0x10..0x28"} {"id": "corpus.Screen_window_WIDTH_accessor_per_version", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Mir Drualga (phrozen_code Discord)", "module": "D2Win", "desc": "To get game render width: D2Win ordinal 10121 (1.09D/1.10), 10132 (1.12A), 10028 (1.13C), 10150 (1.13D); Game.exe+0xFF010 (1.14C), Game.exe+0x101820 (1.14D) | ordinal 10028 for 1.13C ... offset Game.exe+0xFF010 for LoD 1.14C", "source": ["discord:phrozen_code msg 814427192104321044"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Win #10028 (1.13c); Game.exe+0xFF010 (1.14c)"} {"id": "corpus.Text_background_width_height_D2GFX_DrawRecta", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Mir Drualga (phrozen_code Discord)", "module": "D2Win/D2GFX", "desc": "D2Win ordinal 10110 draws a text popup background; helpers 6f8f1fb0 (text->background width, param in EAX) and 6f8f1e80 (text->background height, param in ESI); width/height feed D2GFX_DrawRectangle | 6f8f1fb0, takes text as param1 ... returns background width ... passed into the D2GFX_DrawRectangle function", "source": ["discord:phrozen_code msg 814433786023641159"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Win #10110; 6f8f1fb0 / 6f8f1e80"} {"id": "struct.D2RoomExFlags_enum", "kind": "struct", "status": "sourced", "trust": "sourced", "author": "Silvermane (phrozen_code Discord)", "module": "D2Common", "desc": "RoomEx flag bits incl HAS_WARP_0..7 (0x10-0x800), SUBSHRINE_ROW1-4, HAS_WAYPOINT 0x10000, AUTOMAP_REVEAL 0x40000, NO_LOS_DRAW 0x80000 (line-of-sight draw suppression), HAS_ROOM 0x100000, HASPORTAL 0x400000, POPULATION_ZERO 0x800000 (towns/nospawn), TILELIB_LOADED 0x1000000, PRESET_UNITS_ADDED/SPAWNED, ANIMATED_FLOOR 0x8000000 (river of flame, hell act5) | ROOMEXFLAG_NO_LOS_DRAW = 0x00080000, ... ROOMEXFLAG_ANIMATED_FLOOR = 0x08000000, //animated floors (river of flame, hell act5)", "source": ["discord:phrozen_code msg 819670965113454632"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "RoomEx flag bitfield"} {"id": "corpus.Draw_label_above_player_head_world_to_screen", "kind": "note", "status": "sourced", "trust": "sourced", "author": "Deleted User (phrozen_code Discord)", "module": "D2Client", "desc": "Player is always at center of screen; getting window rect and halving mis-places by ~15-20%. Correct approach converts unit world coords to screen via a world_to_screen routine (diablo2::utils::screen::world_to_screen); unit x/y from get_unit_x/y(player->path) | diablo2::utils::screen::world_to_screen(label->x, label->y, mx, my); Does the trick.", "source": ["discord:phrozen_code msg 818990733540851722"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "world_to_screen"} {"id": "corpus.background_dialog_draw_via_D2gfx_10072", "kind": "function", "status": "sourced", "trust": "sourced", "author": "kain_abel_666 (phrozen_code Discord)", "module": "D2 (custom mod DLL, runtime 0x04D7xxxx)", "desc": "kain_abel_666 located where a background is drawn: a D2gfx.#10072 draw call at 04D72AE5 that takes an X (EAX from [EBP-18C]) and a Y value (EDX from [EBP-190]); he identifies the Y push at 04D72AD0 as the value that is 'messing up' his positioning. Directly a render-pipeline / draw-position problem analogous to ours. | so i figured out where it draws the background ... CALL DWORD PTR DS:[4D76AA4] ; D2gfx.#10072 ... is the Y Value that is messing up", "source": ["discord:phrozen_code msg 824357135319564368"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "call 04D72AE5 -> D2gfx.#10072; Y src [EBP-190]"} {"id": "corpus.ITEMS_InventoryDraw", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Necrolis' reversed inventory item-draw function (draws an item cel inside the inventory/side panel, with overlay support). Shows the full draw path: UNITDRAW_CacheGFXData -> D2LoadCelFile -> GFXUTIL_CellWithinScreen -> D2DrawImage -> UNITDRAW_DrawOverlays. Directly the side-panel render pipeline. | Function: ITEMS_InventoryDraw Address: D2Client.0x6FB5A320 ... BOOL __fastcall ITEMS_InventoryDraw(D2UnitStrc* pItem, int nXpos, int nYpos)", "source": ["discord:phrozen_code msg 789293809699520542"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FB5A320"} {"id": "struct.DLRGTileGrid", "kind": "struct", "status": "sourced", "trust": "sourced", "author": "SwineFlu (phrozen_code Discord)", "module": "D2Common (DRLG)", "desc": "Per-room tile container holding wall/floor/shadow tile data; sizeof 0x2C. Fields: pMapLinks+00, pAnimTiles+04, nWalls+08, nFloors+0C, nShadows+10, pTiles+14. SwineFlu asks whether it can be surgically removed and rebuilt from the room seed without client/server desync. Core of floor/tile rendering data. | struct DLRGTileGrid //sizeof 0x2C { DRLGTileLink* pMapLinks; //+00 ... int nFloors; //+0C int nShadows; //+10 DRLGRoomTiles pTiles; //+14 };", "source": ["discord:phrozen_code msg 826166314899865622"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "sizeof 0x2C; nFloors+0C, nShadows+10"} {"id": "corpus.gScreenWidth_gScreenHeight_globals", "kind": "global", "status": "sourced", "trust": "sourced", "author": "kain_abel_666 (phrozen_code Discord)", "module": "D2Client", "desc": "kain_abel_666 has labelled the client screen-dimension globals: gScreenWidth @ 6FB740EC and gScreenHeight @ 6FB740F0. Relevant to viewport/play-area sizing. | i have the screen width and height labeled as D2Client.gScreenWidth @ 6FB740EC and .gScreenHeight @ 6FB740F0", "source": ["discord:phrozen_code msg 828411605917368351"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "gScreenWidth 6FB740EC, gScreenHeight 6FB740F0"} {"id": "corpus.GetMouseYCoordinate", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Harvest (phrozen_code Discord)", "module": "D2Client", "desc": "D2Client.6FB57BD0 reads global at 6FBC1AE8; Harvest identifies it as GetMouseYCoordinate (RVA 0xB7BD0, __stdcall, no args). Screen-space coordinate accessor. | D2FUNC(D2CLIENT, GetMouseYCoordinate, DWORD, __stdcall, (), 0xB7BD0) //D2Client6FB57BD0", "source": ["discord:phrozen_code msg 828412649171451925"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FB57BD0 (RVA 0xB7BD0); global 6FBC1AE8"} {"id": "corpus.Bottom_UI_panel_button_hook", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Kingpin (phrozen_code Discord)", "module": "D2Client", "desc": "Kingpin: the easy way to add new buttons is to hook the code that draws the bottom UI panel. Points at the panel-draw routine as the injection site. | add new buttons is simple, easiest way is hook part where it draw the bottom ui panel", "source": ["discord:phrozen_code msg 822529352134164571"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use"} {"id": "corpus.D2DrawText_D2Win_10117_item_gfx_GFX_10073", "kind": "function", "status": "sourced", "trust": "sourced", "author": "kain_abel_666 (phrozen_code Discord)", "module": "D2Win / D2gfx", "desc": "kain_abel_666 repositioning D2BuffIcons: text via D2Win.#10117 D2DrawText(pString,nX,nY,nColour,nTransTbl); icon images via GFX.#10073. Asks what -1 as the transtbl arg means. UI-panel overlay positioning. | D2DrawText(wchar_t* pString, int nXpos, int nYpos, int nColour, int nTransTbl); ... the only called to GFX.#10073 for the images", "source": ["discord:phrozen_code msg 828594535499563028"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Win.#10117; GFX.#10073"} {"id": "corpus.Set_item_color_inventory_vs_ground", "kind": "global", "status": "sourced", "trust": "sourced", "author": "oli (phrozen_code Discord)", "module": "D2Client", "desc": "oli: changing set-item color in 1.13c. Ground color patch at 6FB6FF1D works; the inventory (side-panel) copy is a separate address 6FB4408F (changed 02000000 -> 08000000). Concrete evidence that inventory-panel drawing uses a distinct code path from world/ground drawing. | this is the adress for inv 6FB4408F changed 02000000 to 08000000 ... 6FB6FF1D is for the ground and it works", "source": ["discord:phrozen_code msg 830848314698235974"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "inv 6FB4408F, ground 6FB6FF1D"} {"id": "corpus.Item_Click", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Conqueror (phrozen_code Discord)", "module": "D2Client", "desc": "Client-side handler run when clicking an item; takes inventory pointer, mouse X/Y and inventory page. Relevant to side-panel/inventory hit-testing. | //D2Client.0x475C0 D2FUNC(D2CLIENT, Item_Click, int32_t, __fastcall, (D2UnitStrc* pPlayer, D2InventoryStrc* pInventory, int pMouse_X, int pMouse_Y, ui", "source": ["discord:phrozen_code msg 822507812298817596"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x475C0"} {"id": "corpus.gfx_frame_vs_game_frame_dwGfxFrame_dwGfxGame", "kind": "note", "status": "sourced", "trust": "sourced", "author": "Elmegaard (phrozen_code Discord)", "module": "D2Common / D2Game", "desc": "Elmegaard working through a broken gfx-frame bug: proposal to split pUnit->dwGfxFrame from a new dwGfxGameFrame = pGame->dwGameFrame << 8, and where the frame bonus (D2Common_10031_GetFrameBonus << 8) is applied. Animation-frame timing for unit rendering. | pUnit->dwGfxGameFrame = D2Common_10031_GetFrameBonus(pUnit) << 8; pUnit->dwGfxFrame = pGame->dwGameFrame << 8;", "source": ["discord:phrozen_code msg 824677094184189972"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Common #10031 GetFrameBonus"} {"id": "corpus.UNITS_GetInventoryRecordId", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Conqueror (phrozen_code Discord)", "module": "D2Common", "desc": "Gets the inventory record id for a unit/inv page (Inventory.txt). Used for inventory/panel geometry. | //D2Common.0x6FDBEBE0 (#10409) int __stdcall UNITS_GetInventoryRecordId(D2UnitStrc* pUnit, int nInvPage, BOOL bLoD)", "source": ["discord:phrozen_code msg 822513262238629948"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Common.0x6FDBEBE0 (#10409)"} {"id": "corpus.STATES_GetGfxStateFlags_STATES_GetStatFlags", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Conqueror (phrozen_code Discord)", "module": "D2Common", "desc": "Two state-flag accessors returning DWORD* into a unit's state bitfield: #10492 GetGfxStateFlags @0x6FDB4760, #10494 GetStatFlags @0x6FDB48F0. GfxStateFlags governs which overlay/graphic states are active on a unit. | //D2Common.0x6FDB4760 (#10492) DWORD* __stdcall STATES_GetGfxStateFlags(D2UnitStrc* pUnit) ... //D2Common.0x6FDB48F0 (#10494)", "source": ["discord:phrozen_code msg 822229046074540103"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "#10492 0x6FDB4760; #10494 0x6FDB48F0"} {"id": "struct.D2StaticPathStrc", "kind": "struct", "status": "sourced", "trust": "sourced", "author": "Silvermane (phrozen_code Discord)", "module": "D2Common", "desc": "Static path struct (used by items/objects on ground): pRoom@0x00, nTargetX@0x04, nTargetY@0x08, nXPos@0x0C, nYPos@0x10, unk[2]@0x14, nDirection(BYTE)@0x1C. (Canight variant puts dwHeight@0x50.) Ground-position data feeding unit placement. | struct D2StaticPathStrc { D2RoomStrc* pRoom; //0x00 int nTargetX; //0x04 ... int nXPos; //0x0C int nYPos; //0x10 ... BYTE nDirection; //0x1C };", "source": ["discord:phrozen_code msg 826937887588745257"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "pRoom+00, nXPos+0C, nYPos+10, nDirection+1C"} {"id": "corpus.PLAYERMODE_Change", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Game", "desc": "Necrolis: void __fastcall PLAYERMODE_Change(pGame,pPlayer,pSkill,BYTE nMode,int nUnitType,DWORD dwGUID,BOOL bAllowReEnter) at D2Game.0x6FC81A00 (RVA 0x51A00). Changes a unit's animation/mode. | Function: PLAYERMODE_Change Address: D2Game.0x6FC81A00 ... void __fastcall PLAYERMODE_Change(D2GameStrc* pGame, D2UnitStrc* pPlayer, D2SkillStrc* pSki", "source": ["discord:phrozen_code msg 829123022946172969"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Game.0x6FC81A00 (0x51A00)"} {"id": "corpus.D2Client_SkillDesc_formatting_hooks", "kind": "note", "status": "sourced", "trust": "sourced", "author": "Conqueror (phrozen_code Discord)", "module": "D2Client", "desc": "Skill-description decimal precision fix; hook points in D2Client at 0x73438 (capture value), 0x73495 (fix), 0x73458 (exit-if-zero), with returns 0x7343D/0x734A1/0x73472. This is on the skill-description UI text render path. | { D2DLL_D2CLIENT, 0x73438, (DWORD)PATCH_JMP, FALSE, 0x1 }, { D2DLL_D2CLIENT, 0x73439, (DWORD)SkillDescCaptureValue, TRUE, 0x0 }", "source": ["discord:phrozen_code msg 830891740713713684"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "0x73438 / 0x73495 / 0x73458 (rets 0x7343D/0x734A1/0x73472)"} {"id": "corpus.gpCurrentMouseOverItem", "kind": "global", "status": "sourced", "trust": "sourced", "author": "erevos (phrozen_code Discord)", "module": "D2Client", "desc": "Global holding the item the cursor is hovering (inventory/ground); compared at D2Client 6FAE10A1 as CMP ESI,[gpCurrentMouseOverItem] (ptr at 0x1732BC4 in the BlackSSE build). Directly tied to inventory/panel item interaction. | 6FAE10A1 |> 3B35 C42B1703 |CMP ESI,DWORD PTR DS:[BlackSSE.gpCurrentMouseOverItem", "source": ["discord:phrozen_code msg 850687267148136468"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FAE10A1 / gpCurrentMouseOverItem (172BC4)"} {"id": "corpus.Automap_level_name_hardcoded_table_8E2D0", "kind": "note", "status": "sourced", "trust": "sourced", "author": "Deleted User (phrozen_code Discord)", "module": "D2Common", "desc": "v1.10 automap.txt loader compares level names against a hardcoded 36-entry table at D2Common offset 0x8E2D0 (from lvltypes.txt), which breaks level types past 36; fix substitutes a lvltypes record-index field. Relevant to floor/tile/automap level handling. | The existing loader function in v1.10 for automap.txt compares the level names against a hardcoded table at d2common offset 8E2D0 ... has only 36 entr", "source": ["discord:phrozen_code msg 853309589600600075"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "0x8E2D0"} {"id": "corpus.Rain_render_tied_to_GetRainFromLevelsTxt", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Lectem (phrozen_code Discord)", "module": "D2Client", "desc": "D2Client.0x6FAA8870 was thought to control rain but actually just reflects the result of D2COMMON_10632_GetRainFromLevelsTxt (weather from levels.txt) - a client display value. | D2Client.0x6FAA8870 ... it's actually just updated to reflect the results of D2COMMON_10632_GetRainFromLevelsTxt", "source": ["discord:phrozen_code msg 853388416547684382"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "0x6FAA8870 / D2Common #10632"} {"id": "corpus.D2Common_10177_usage_D2PathPointStrc_X_unsig", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Lectem (phrozen_code Discord)", "module": "D2Client", "desc": "D2Common_10177 (returns 32-bit) is consumed in D2Client.0x6FB49D70; lack of sign-extension when moving from D2PathPointStrc implies D2PathPointStrc::X is unsigned. Path point coords feed positional/camera math. | looking at the usage of D2Common_10177 in D2Client.0x6FB49D70 ... D2PathPointStrc::X is unsigned", "source": ["discord:phrozen_code msg 855768674119057419"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "0x6FB49D70 / D2Common #10177"} {"id": "corpus.main_UI_loop_ALT_item_box_draw", "kind": "function", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2Client", "desc": "whist: 0xC39E0 is the main ui loop where all panels are rendered; it calls 0x58FB0 which draws the boxes shown when ALT is pressed to show ground items; hookable via d2template | at D2Client.0xC39E0 is the main ui loop where all the different panels are rendered ... a call to D2Client.0x58FB0, which is the function that handles", "source": ["discord:phrozen_code msg 880233097780678656"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0xC39E0 (main UI loop); D2Client.0x58FB0 (ALT item box draw)"} {"id": "corpus.HD_PanelPosition_Interception", "kind": "note", "status": "sourced", "trust": "sourced", "author": "Stephen Lynx (phrozen_code Discord)", "module": "D2Client", "desc": "A patch that intercepts panel positioning at 0xC39F7 (one past the 0xC39E0 UI loop region) | { D2DLL_D2CLIENT, 0xC39F7, 38, (int)HD::PanelPosition_Interception, TRUE }", "source": ["discord:phrozen_code msg 880225275382751232"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client 0xC39F7 (size 38, PATCH... TRUE)"} {"id": "corpus.INTERFACE_CORE_InputAndOutputMsgWindow", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Conqueror (orig Araksson) (phrozen_code Discord)", "module": "D2Client", "desc": "Master click/message dispatcher for all menu panels; found by locating the 4 adjacent Storm#414-417 Input* calls, the function just before them handles all menu clicks; called ~40 times, one callback per panel type; callbacks share globals with the drawing function | the function immediately before is the one that controls all the Clicks of the Menus ... called about 40 times ... one for each type of Panel", "source": ["discord:phrozen_code msg 886284373895303179"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x26C0 (1.13d)"} {"id": "struct.D2ClientFnMsg_D2WinMSGS_CLT", "kind": "struct", "status": "sourced", "trust": "sourced", "author": "Conqueror (phrozen_code Discord)", "module": "D2Client", "desc": "Per-panel message table entry: param, key, __stdcall callback taking D2WinMsgStrc* | struct D2ClientFnMsg { uint32_t dwPar; DWORD dwKey; D2WinMSGS_CLT pCallback; };", "source": ["discord:phrozen_code msg 886284699880804453"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "{dwPar, dwKey, pCallback}"} {"id": "corpus.UIPanelDrawYOffset_UIPanelDrawXOffset", "kind": "global", "status": "sourced", "trust": "sourced", "author": "Kieran (phrozen_code Discord)", "module": "D2Client", "desc": "Client panel draw offset globals used to compute inventory/stash/cube item positions; X offset scales with resolution width (simple), Y offset value (e.g. 196) source is unclear and larger than expected — used for resolution-height support of an item mover | D2VAR(D2CLIENT, UIPanelDrawYOffset, signed int, 0x124958)", "source": ["discord:phrozen_code msg 886292519321739334"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "UIPanelDrawYOffset RVA 0x124958"} {"id": "corpus.Resolution_adaptive_panel_coordinate_math", "kind": "note", "status": "sourced", "trust": "sourced", "author": "Conqueror (Araksson code) (phrozen_code Discord)", "module": "D2Client", "desc": "Panel button hit-test computes coords from screen width/height minus WindowStartX/Y plus fixed offsets (e.g. -0x12e..-0x10e X, -0x60..-0x40 Y); Conqueror advises deriving positions from screen-width/window-width constants and half-screen center + cursor offset for dragging | (BLSS_CLIENT_GetScreenWidth() - BLSS_CLIENT_WindowStartX()) + -0x12e <= mouse_x", "source": ["discord:phrozen_code msg 886319508703281192"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "BLSS_CLIENT_GetScreenWidth/Height, WindowStartX, NegWindowStartY"} {"id": "corpus.DRLGROOM_AllocRoomNears_ReAllocRoomNears_roo", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Conqueror (Araksson/D2Moo) (phrozen_code Discord)", "module": "D2Common", "desc": "Builds each room's ppRoomsNear list by scanning level rooms within tile distance <10 in X and Y (nTileXPos/YPos/Width/Height), sorts by position; D2Moo raises near cap 6->10 (ppNearRooms[1024]) | Function: DRLGROOM_AllocRoomNears Adress: D2Common.0x6FD77BB0 ... Improvement 6 --> 10", "source": ["discord:phrozen_code msg 886327659028701186"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Common.0x6FD77BB0 / 0x6FD77F00"} {"id": "corpus.Multires_additional_room_floor_drawing_Slugg", "kind": "note", "status": "sourced", "trust": "sourced", "author": "SwineFlu (phrozen_code Discord)", "module": "D2Client", "desc": "To fill missing tiles at higher resolution: iterate nearby rooms excluding those the client already drew, and do additional drawing for rooms visible from client's perspective. FLOOR tiles are drawn by a SEPARATE function from wall/roof tiles and units — two distinct functions, both called recursively. Directly relevant to filling the black play-area/dead-zone with world tiles | Floor tiles are handled separately from wall/roof tiles and units - hence why there are two distinct functions ... These two functions are also called", "source": ["discord:phrozen_code msg 862314978442084372"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "n/a (based on Necrolis reversed multires code, d2mods.info t=59615)"} {"id": "corpus.Screen_shift_struct_must_be_extended", "kind": "note", "status": "sourced", "trust": "sourced", "author": "LAZ (phrozen_code Discord)", "module": "D2Client", "desc": "LAZ: to add a NEW screen/UI shift without disturbing existing behavior, you must extend the shift struct | if you want a new shift that doesn't affect other stuff, you might have to extend that struct", "source": ["discord:phrozen_code msg 866391215921823764"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "n/a"} {"id": "corpus.palshift_Translvl_column_patch", "kind": "global", "status": "sourced", "trust": "sourced", "author": "eezstreet / LAZ (phrozen_code Discord)", "module": "D2Client", "desc": "eezstreet: first two palshifts are ignored; changing 0x6FB27A23 to 'mov edi,0' shifts back the Translvl column so must add 2. Item draw uses the color index (one of 21) as offset into the transform/invtransform shift | Even if I change 0x6FB27A23 to be mov edi, 0 it will just shift back the Translvl column", "source": ["discord:phrozen_code msg 866735352093474846"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client 0x6FB27A23"} {"id": "corpus.ITEMDESC_DrawGroundMultiHover", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Draws multi-item ground hover boxes; second half is the relevant part; uses FONTS_GetTextDimensions then nWidth += 8 for box sizing | Function: ITEMDESC_DrawGroundMultiHover Address: D2Client.0x6FB09F60", "source": ["discord:phrozen_code msg 893161403094032395"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FB09F60"} {"id": "struct.D2AutoMapRecordStrc_gpMapGfxCells_gpfMapName", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "Kingpin (phrozen_code Discord)", "module": "D2Common", "desc": "Automap graphics cell first/last per level type; level-type name table (0=None..44) drives automap tile ranges; two dword patches point the engine at an enlarged name table | D2AutoMapRecordStrc gpMapGfxCells[MAX_LEVELTYPES]; ... struct { int nFirst; int nLast; }", "source": ["discord:phrozen_code msg 890306115924033576"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "MAX_LEVELTYPES 255; patch CommonOffset+0x22AF5 and +0x22B32"} {"id": "corpus.D2Client_top_level_UI_control_panel_exp_bar_", "kind": "function", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2Client", "desc": "Single top-level handler that draws the entire bottom control panel and the exp bar. NOPing its no-arg calls reveals what each sub-call draws. | that's the function I mentioned ... D2Client.0xC39E0 (top level handler necrolis mentioned)", "source": ["discord:phrozen_code msg 969922337015226410"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0xC39E0"} {"id": "corpus.Bottom_panel_input_handler_NOP_sites", "kind": "note", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2Client", "desc": "Patch sites (NOPBLOCK, 0x15 bytes) that disable the bottom-panel input handlers; input handlers are separate from the draw code. | Disable bottom panel input handlers", "source": ["discord:phrozen_code msg 966731514656227328"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "0xC1C76,0xC2224,0xC2D51,0xC3792,0xC37AD (0x15 bytes each)"} {"id": "corpus.Mini_panel_input_handler_NOP_sites", "kind": "note", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2Client", "desc": "Patch sites (NOPBLOCK 0x15) that disable the mini-panel input handlers. | Disable mini panel input handlers", "source": ["discord:phrozen_code msg 969922337015226410"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "0x29431,0x29534,0x37927,0x37D43,0xC1EEA,0xC24CB,0xC3043,0xC3061"} {"id": "corpus.Find_panel_draw_vs_input_code", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Control panel + exp bar draw from one top-level handler; NOP the no-arg calls to see what draws what. Click/input handlers are NOT part of draw code and can be found via storm ordinal #511. | You can NOP out the calls with no args to quickly see what draws what ... find any input handler via that ordinal", "source": ["discord:phrozen_code msg 969628110716821524"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "storm.#511"} {"id": "corpus.ControlPanel_OrbTextDisplay", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Szumigajowy (phrozen_code Discord)", "module": "D2Client", "desc": "Renders the orb text (life/mana orb display) on the control panel. | Function: ControlPanel::OrbTextDisplay Address: D2Client.0x6FAFF0B0", "source": ["discord:phrozen_code msg 969983765315223663"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FAFF0B0"} {"id": "corpus.Find_what_draws_a_loaded_asset", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "To locate draw code for an asset, find READS of the asset's data pointer, not the load code. Example pointer 6FBCBC80. | to find what draws it you need to look for reads of 6FBCBC80", "source": ["discord:phrozen_code msg 970944749454393384"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "reads of 6FBCBC80"} {"id": "corpus.RoomTile_flag_setter_tile_dwFlags_bit_8", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Szumigajowy (phrozen_code Discord)", "module": "D2Common", "desc": "Sets bit 8 of pTileData->dwFlags from the sign bit (0x80000000) of nTileFlags; floor/room tile flag handling. | 0x6FD88AC0 ... if (nTileFlags & 0x80000000) pTileData->dwFlags |= 8", "source": ["discord:phrozen_code msg 957257983442710558"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Common.0x6FD88AC0"} {"id": "corpus.RoomExFlag_0x80000000", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Lectem (phrozen_code Discord)", "module": "D2Common", "desc": "Unnamed RoomEx flag bit; room-tile relevant, asked but unnamed. | anybody has a name for RoomExFlag 0x80000000 ?", "source": ["discord:phrozen_code msg 957250305706315797"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "0x80000000"} {"id": "struct.D2VendorChainStrc", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "Kingpin (phrozen_code Discord)", "module": "D2Game", "desc": "Vendor gamble/inventory chain, size 0xC: +0x00 dwPlayerGUID, +0x04 bGamble (whether sold item appears in vendor inventory), +0x08 pPrev. | struct D2VendorChainStrc //sizeof 0xC { DWORD dwPlayerGUID; BOOL bGamble; D2VendorChainStrc* pPrev; }", "source": ["discord:phrozen_code msg 963391502522933308"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "+0x04"} {"id": "corpus.Inventory_charm_req_code_region", "kind": "global", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2Client", "desc": "whist's old notes point here for higher-level inventory/charm-requirement handling. | old notes pointing to D2Client.0x95AB8", "source": ["discord:phrozen_code msg 983416073179238430"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x95AB8"} {"id": "corpus.Item_charm_cell_background_color_draw_block", "kind": "global", "status": "sourced", "trust": "sourced", "author": "Deleted User (phrozen_code Discord)", "module": "D2Client", "desc": "Pushes RGB values and calls draw (0000D390) to set inventory item cell background colors: red-requirement bg, hover bg, default blue bg. Bytes stored at 6FBBB330-334. | PUSH 80 -> red color (red requirement background) ... default blue background", "source": ["discord:phrozen_code msg 983438747871895563"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "0x8C6B0 (writes 6FBBB330-6FBBB334)"} {"id": "corpus.Charm_blue_background_jump", "kind": "note", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2Client", "desc": "When charm reqs are met, jump gives the charm a blue background (Firehawk 2019 note). Cited by our own Doug. | reqs met, give charm a blue background ... JMP D2Client.6FB45803", "source": ["discord:phrozen_code msg 983404210446016582"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.6FB6C52B -> 6FB45803"} {"id": "corpus.New_high_res_stat_page_panel_decompile_d2exp", "kind": "note", "status": "sourced", "trust": "sourced", "author": "Sophia Philonous (phrozen_code Discord)", "module": "D2Client", "desc": "Plan to decompile d2expres in Ghidra to load a high-res DC6 for a new stat page and make its button work. | decompile d2expres in ghidra, and see if anything there seems like it may let us load a high res dc6 for new stat page and make the button work", "source": ["discord:phrozen_code msg 986407206343827478"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use"} {"id": "corpus.NewInterface_Stats_DC6_panel_draw", "kind": "note", "status": "sourced", "trust": "sourced", "author": "Sophia Philonous (phrozen_code Discord)", "module": "D2Client", "desc": "Custom stats interface: loads a DC6 and blits frames via D2PrintImage at panel coordinates (0,256),(256,256),(0,512),(256,512),(0,552) then fillRect(0,0,400,552). Extra frames 6/7 don't render. Uses setImage/setFrame/D2PrintImage/fillRect helpers; palette index 5. | NewInterface_Stats.cpp is containing this code, where it loads the dc6 ... D2PrintImage(&data, 0, 256, -1, 5, 0);", "source": ["discord:phrozen_code msg 984434446372773910"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use"} {"id": "corpus.Porting_1_10_hooks_to_1_13c_requires_offset_", "kind": "note", "status": "sourced", "trust": "sourced", "author": "Sophia Philonous (phrozen_code Discord)", "module": "D2Client", "desc": "Doug (Esoteric Path/Sophia) notes porting functions/hooks from 1.10 to 1.13c requires shifting all offsets and re-hooking. | It would require too much work to shift offsets from 1.10, hook those functions. Etc.", "source": ["discord:phrozen_code msg 989485415805354014"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use"} {"id": "corpus.Alt_item_ground_item_name_drawing_palette_dr", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Item-on-ground nameplate rendering. When Alt held, MOV DWORD PTR [EBP+118] sets draw mode: 6FB0933F sets 1 (regular items), 6FB09306 sets 5 (hovered item). Can hook 6FB0946E CALL D2Win.#10013 to override palette/draw mode. Single nameplate (alt not held) at 6F8F356C PUSH 2. | else you can just hook: 6FB0946E CALL and replace the values for palette and draw mode yourself", "source": ["discord:phrozen_code msg 998697058225639536"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FB0933F / 6FB09306 / 6FB0946E (D2Win.#10013) / 6F8F356C"} {"id": "corpus.Remove_skill_tab_hover_text_black_background", "kind": "note", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2Client", "desc": "1.13c: forced a conditional jump to unconditional JMP at D2Client 6FB28092 -> 6FB281BF to eliminate the 'Skill Tab 1' hover text plus its black background box. | 6FB28092 E9 28010000 JMP D2Client.6FB281BF ... eliminated it", "source": ["discord:phrozen_code msg 1001361521957404783"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FB28092 JMP 6FB281BF (offset 0x28092)"} {"id": "corpus.Level_entry_level_name_DC6_display_routine", "kind": "note", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2Client", "desc": "Whilst's edit controlling the level-name DC6 shown on level change. At D2Client BF33F (6FB6F337): reads [6FB8BC4C], CDQ/SUB/SAR, PUSH 1 (palshift), PUSH 5 (draw mode), SUB EAX,8C (vertical position), PUSH 1 (horizontal position). Routine begins at 6FB6F0D0 (reads [6FBCBBFC]); called from 6FB73AA1. | 6FB6F345 2D 8C000000 SUB EAX,8C ;vertical position 6FB6F34A 6A 01 PUSH 1 ;horizontal position", "source": ["discord:phrozen_code msg 1003355799143329802"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FB6F337 (0xBF33F); routine start 6FB6F0D0; caller 6FB73AA1"} {"id": "corpus.Level_entry_DC6_caller_site", "kind": "note", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2Client", "desc": "CALL D2Client.6FB6F0D0 at 6FB73AA1 is the sole call site of the level-entry display routine; nearby CMP [6FBCC414],3 and CALL 6FB12680 / 6FB0C5C0 / CMP [6FBAADCC]. | 6FB73AA1 |> E8 2AB6FFFF CALL D2Client.6FB6F0D0 <--- here", "source": ["discord:phrozen_code msg 1003370916312514741"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FB73AA1 -> CALL 6FB6F0D0"} {"id": "struct.D2DrlgStrc_active_room_offsets", "kind": "struct", "status": "sourced", "trust": "sourced", "author": "SwineFlu (phrozen_code Discord)", "module": "D2Common", "desc": "1.13c D2DrlgStrc fields: +0x098 (=1.10 +0x3E0, DWORD added-active-rooms counter, never decremented), +0x45C (=1.10 +0x3DC, BYTE counter, can overflow), +0x008 (=1.10 +0x3DD, set to 5 or 7 per +0x24 dwFlags, can be decremented). Client-side active-room processing; see D2Common.#10715 (1.13c) / #10003 (1.10). | offsets for these fields in 1.13c are D2DrlgStrc +0x098 +0x45C +0x008 ... 0x3E0 is the amount of added active rooms", "source": ["discord:phrozen_code msg 1010561899705929758"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2DrlgStrc +0x098/+0x45C/+0x008 (1.13c); +0x3E0/+0x3DC/+0x3DD (1.10)"} {"id": "corpus.UNITDESC_DrawInformation", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "void __fastcall UNITDESC_DrawInformation(D2UnitStrc* pUnit) at D2Client.0x6FB20A30 (1.10). Draws the unit info/nameplate; contains a large per-unit-type switch that looks up the display name. Render-relevant (unit nameplate drawing). | Function: UNITDESC_DrawInformation Address: D2Client.0x6FB20A30 ... large switch inside it for each unit type", "source": ["discord:phrozen_code msg 1031581281173110888"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FB20A30 (1.10)"} {"id": "corpus.Monster_desc_immunities_drawing_edits", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Client monster-description block (immunities/minion text) around 6FB2100D. NOP the TEST EAX/JNZ at 6FB2100D to append monstats to minions/uniques; also adjust MOV EAX,13 at 6FB22167 and ADD EAX,31 at 6FB221D0. Underlying draw call at 6FB20600. D2Client based at 6FAA0000. | 6FB2100D ... 90 NOP ... 6FB22167 B8 13000000 MOV EAX,13 ... 6FB221D0 83C0 31 ADD EAX,31", "source": ["discord:phrozen_code msg 1046822911937368124"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FB2100D / 6FB22167 / 6FB221D0 / 6FB20600"} {"id": "corpus.Skill_speed_bars_attack_speed_positioning", "kind": "note", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2Client", "desc": "1.13c D2Client attack/cast speed bars for left/right click. Draw routine at 6FAEE7F0 (SUB ESP,124; MOV EAX,[6FB8BC4C]; ADD EAX,-56 vertical position). Horizontal position set by PUSH 50 (Arg2) at 6FAEEC24 — that section holds left bar, right bar, and mouseover icon values. | 6FAEEC24 |. 6A 50 PUSH 50 ; |Arg2 = 00000050 ... values for the icons for the left skill bar, right skill bar", "source": ["discord:phrozen_code msg 1050552446042259567"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FAEE7F0 (0xEE7F0); horiz PUSH 50 at 6FAEEC24"} {"id": "corpus.Frameless_loop_sleep_flag", "kind": "global", "status": "sourced", "trust": "trusted", "author": "Lectem (phrozen_code Discord)", "module": "D2Client", "desc": "Boolean set TRUE in most cases (solo) that governs the game's sleep; main loop otherwise spins with no vsync, which is why removing the frame limit is easy | it does have a sleep but D2Client.0x6FB747C0 is set to TRUE in most cases", "source": ["discord:phrozen_code msg 1056652444353953903"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "0x6FB747C0"} {"id": "corpus.Hot_boot_profiling_function", "kind": "global", "status": "sourced", "trust": "trusted", "author": "Lectem (phrozen_code Discord)", "module": "D2Client", "desc": "Function so hot that profiling it makes the game slow to boot (likely main-loop / per-frame) | why profiling 0x6FAA9AF0 made the game so slow to boot", "source": ["discord:phrozen_code msg 1056652892804751360"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "0x6FAA9AF0"} {"id": "corpus.Health_mana_globe_15_16_bit_widening", "kind": "note", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2Game/D2Client", "desc": "HP/mana/stamina sent as 15-bit fields in one packet; change the 15 to 16 at three server + three client sites to raise the ~65k limit (1.13c) | just gotta change the 15 to 16 at these three locations (1.13c) D2Game.0x8B81B D2Game.0x8B82D D2Game.0x8B83F", "source": ["discord:phrozen_code msg 1071978990119702622"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Game 0x8B81B/0x8B82D/0x8B83F; D2Client 0xAC1CF/0xAC1DB/0xAC1EB"} {"id": "corpus.Stamina_bar_draw_color_palette", "kind": "function", "status": "sourced", "trust": "sourced", "author": "DannyIsGreat (phrozen_code Discord)", "module": "D2Client", "desc": "Function responsible for drawing the stamina bar; 0x7BEFBA is an array of palette indexes picking bar color by remaining stamina | 0x4975B0. that is the func responsible for drawing the stamina bar ... 0x7BEFBA is an array of pallette indexes", "source": ["discord:phrozen_code msg 1081288802762510428"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "draw 0x4975B0, palette-index array 0x7BEFBA"} {"id": "corpus.XP_bar_draw", "kind": "function", "status": "sourced", "trust": "sourced", "author": "DannyIsGreat (phrozen_code Discord)", "module": "D2Client", "desc": "Function that draws the experience bar | try looking at 0x498EA0 for xp bar", "source": ["discord:phrozen_code msg 1082377413289312316"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "0x498EA0"} {"id": "struct.D2EnvironmentCycleStrc_day_night_tint_tables", "kind": "struct", "status": "sourced", "trust": "sourced", "author": "Conqueror (phrozen_code Discord)", "module": "D2Client", "desc": "Environment lighting cycle tables: {angle, phase, R,G,B, 0} keyframes driving the screen ambient color tint per act | const D2EnvironmentCycleStrc gNormalEnvironmentCycle[6] = { { 320, 3, 125, 144, 243, 0 }, ...", "source": ["discord:phrozen_code msg 1080319832764981269"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "gNormalEnvironmentCycle / gAct4EnvironmentCycle / gEclipseEnvironmentCycle [6]"} {"id": "corpus.HoverObjectPatch_custom_monster_bar_draw", "kind": "note", "status": "sourced", "trust": "sourced", "author": "Rayveen (phrozen_code Discord)", "module": "D2Client", "desc": "Hover-object hook draws custom DC6 frames (hp/res frames) at hardcoded screen coords via D2GFX_DrawShiftedImage when hovered unit is an enemy monster matching a txt id | D2GFX_DrawShiftedImage(&ChesRes, 90, 17, -1, 5, 0);// hp frame", "source": ["discord:phrozen_code msg 1092266022138019870"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use"} {"id": "corpus.DUNGEON_StreamRoomAtCoords", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Lectem (phrozen_code Discord)", "module": "D2Common", "desc": "D2RoomStrc* __stdcall DUNGEON_StreamRoomAtCoords(D2DrlgActStrc* pAct, int nX, int nY) — resolves the room at world coords | D2RoomStrc* __stdcall DUNGEON_StreamRoomAtCoords(D2DrlgActStrc* pAct, int nX, int nY)", "source": ["discord:phrozen_code msg 1103216679896494131"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "0x6FD8C730 (#10065)"} {"id": "corpus.DRLG_AllocLevel_D2DrlgLevelStrc_fields", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Silvermane (phrozen_code Discord)", "module": "D2Common", "desc": "Allocates a DRLG level from mempool; sets pDrlg, nLevelId, nLevelType, nDrlgType from DATATBLS_GetLevelDefRecord | D2DrlgLevelStrc* __fastcall DRLG_AllocLevel(D2DrlgStrc* pDrlg, int nLevelId)", "source": ["discord:phrozen_code msg 1107172977637871626"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "0x6FD748D0 (#10013)"} {"id": "corpus.Automap_custom_icon_via_Miniicons_RevealRoom", "kind": "note", "status": "sourced", "trust": "sourced", "author": "Rayveen (phrozen_code Discord)", "module": "D2Client", "desc": "Walks Room2->pPreset PresetUnit chain; sets cellNo into Maximap.dc6 to draw custom automap icons for preset units/shrines (shrine list by dwTxtFileNo, Type 0x0F) | void Miniicons::RevealRoom(Room2* room) { for (PresetUnit* preset = room->pPreset; ...) ... cellNo = 1499;", "source": ["discord:phrozen_code msg 1107660373382934548"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "Maximap.dc6 cellNo 1499/310/1501"} {"id": "struct.D2TileStrc", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Common/tooling", "desc": "Full tile struct layout for floor/tile rendering: +00 nDirection, +04 nRoofHeight, +06 fMaterial, +08 nHeight, +0C nWidth, +10 nHeightToBottom, +14 nType, +18 nStyle, +1C nSequence, +20 nRarity/nFrame union, +24 dw24To8BitFilterMask, +28 fTileFlags[26] (first byte index, 25 subtile flags), +42 wCacheIndex, +44 dwUnk44, +48 dwBlockOffset, +4C nBlockSize, +50 nBlocks, +54 pBlock, +58 pLibraryName (runtime), +5C pLRUCac | struct D2TileStrc //sizeof 0x60 { int32_t nDirection; //+00 ... int32_t nHeightToBottom; //+10 ... D2TileBlockStrc* pBlock; //+54", "source": ["discord:phrozen_code msg 1152247697089237013"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "sizeof 0x60"} {"id": "corpus.INTERFACE_FillRender", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Conqueror (phrozen_code Discord)", "module": "D2Client", "desc": "The callback that fills the Units renderer structure to later draw; invoked from D2Common.#10049 DUNGEON_CallRoomCallback. Central to the play-area unit render pipeline. Signature: BOOL __stdcall INTERFACE_FillRender(D2RoomStrc* pRoom, D2GameViewRenderDataCallBackStrc* pArgs). Hazel hit a crash here throwing many-CtC items into a crowd. | This is a callback from D2Common.#10049 (DUNGEON_CallRoomCallback). It is the function that is responsible for filling the Units renderer structure to", "source": ["discord:phrozen_code msg 1216375610121912421"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FAB8290 (sub_6FAB8290)"} {"id": "struct.D2RoomCullArgsStrc", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client/D2Common", "desc": "Args struct for room culling during render: +00 D2ViewStrc* pView, +04 RECT pCullingRect, +14 DRLGRoom* pClientRoom, +18 BOOL bTilesOnly. Directly about the viewport/culling rectangle that decides what tiles/rooms get drawn -- relevant to play-area vs panel clipping. | struct D2RoomCullArgsStrc { D2ViewStrc* pView; //+00 RECT pCullingRect; //+04 DRLGRoom* pClientRoom; //+14 BOOL bTilesOnly; //+18 };", "source": ["discord:phrozen_code msg 1217814557364326510"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "+00..+18"} {"id": "corpus.FONTS_DrawHoverText_D2Win", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Silvermane (phrozen_code Discord)", "module": "D2Win", "desc": "Hover/tooltip text draw. Clamps X/Y against screen size via D2GFX_GetScreenSize(&nGameWidth,&nGameHeight); positions box so it stays on screen (nXpos > nGameWidth-nWidth -> nGameWidth-nWidth-5). Draws background via D2GFX_DrawSolidRectEx. Shows how the game reads viewport dimensions for UI placement -- the nGameWidth/nGameHeight globals bound the drawable area. | D2GFX_GetScreenSize(&nGameWidth, &nGameHeight); ... if ((uint32_t)nXpos > nGameWidth - nWidth) nXpos = nGameWidth - nWidth - 5;", "source": ["discord:phrozen_code msg 1212586804361043999"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Win.6F8AA6E0"} {"id": "corpus.Panel_always_display_patch_button_visibility", "kind": "global", "status": "sourced", "trust": "sourced", "author": "DannyIsGreat (phrozen_code Discord)", "module": "D2Client", "desc": "NOP-ing CMP DWORD PTR DS:[6FBBA6FC],EBX / JE at 6FB22062-6FB22068 makes a UI panel always displayed, but its buttons stop working when 'closed'. 6FBBA6FC is the panel-open global flag. Relevant to forcing side panels on. | nooping the following will make it always displayed, but the buttons won't work if u \"close\" the panel. 6FB22062 |. 391D FCA6BB6F CMP DWORD PTR DS:[6F", "source": ["discord:phrozen_code msg 1138481820313333781"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FB22062 / global 6FBBA6FC"} {"id": "corpus.Panel_button_click_handler", "kind": "global", "status": "sourced", "trust": "sourced", "author": "DannyIsGreat (phrozen_code Discord)", "module": "D2Client", "desc": "6FB00CD0 is the handler for when you click that (panel) button; NOP everything up to the retn 4 to disable the click action. | 6FB00CD0 i think is the handler for when u click that button. if u basically noop everything up to the retn 4 it'll disable what happens when u click ", "source": ["discord:phrozen_code msg 1138817708771778580"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FB00CD0"} {"id": "corpus.Waypoint_panel_draw", "kind": "function", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2Client", "desc": "Function that draws the waypoint panel in 1.13c. Active tab is a D2Client global variable (no server round-trip to switch tabs). Good entry point for locating panel-tab state globals. | the function that draws the waypoint panel (D2Client.0xAAEC0 on 1.13c)", "source": ["discord:phrozen_code msg 1223937723400851558"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0xAAEC0 (1.13c)"} {"id": "struct.WaypointClientData", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2Client", "desc": "Client-local simplified struct used to draw the waypoints panel: +00 int levelId, +04 byte activated. Client keeps its own copy separate from server PlayerData waypointData. | the client has it's own local copy, and also uses a separate simplified struct to draw the waypoints panel // D2Client.0xFCD8C struct WaypointClientDa", "source": ["discord:phrozen_code msg 1220567460403609681"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0xFCD8C"} {"id": "corpus.CDraw_Game_UI_INTERFACE_DrawUnitSelectedName", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Conqueror (phrozen_code Discord)", "module": "D2Client", "desc": "Draws the selected-unit name over the play area. Two names for same addr: D2FUNC CDraw_Game_UI (0x80A30) and Araksson's INTERFACE_DrawUnitSelectedName (void __fastcall(D2UnitStrc*)). Silvermane long wanted to rewrite this hover-name function. | Function: INTERFACE_DrawUnitSelectedName Adress: D2Client.0x80A30 void __fastcall INTERFACE_DrawUnitSelectedName(D2UnitStrc* pUnit)", "source": ["discord:phrozen_code msg 1221493565935452282"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x80A30 (6FB20A30)"} {"id": "corpus.UI_DrawGroundHoverItem", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Silvermane (phrozen_code Discord)", "module": "D2Client", "desc": "Draws the ground item hover name in the play area: void __fastcall UI_DrawGroundHoverItem(D2UnitStrc* pItem, wchar_t* pBuffer, int nSize). | //D2Client.6FB20740 void __fastcall UI_DrawGroundHoverItem(D2UnitStrc* pItem, wchar_t* pBuffer, int nSize)", "source": ["discord:phrozen_code msg 1213211638128181289"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.6FB20740"} {"id": "corpus.Ground_unit_name_lookup_funcs", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "D2Client.0x6FADD360 handles item names only; D2Client.0x6FB297F0 works for everything but players and vistiles (items always return base name). Used to resolve hovered-unit display names. | D2Client.0x6FADD360 is purely for item names, D2Client.0x6FB297F0 works for everything but players and vistiles", "source": ["discord:phrozen_code msg 1213218371198259221"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FADD360 / 6FB297F0"} {"id": "corpus.MENUS_DrawRegisteredControls_menu_input_hand", "kind": "function", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2Win", "desc": "OOG (out-of-game) menu draw/input entry points (1.13c): MENUS_DrawRegisteredControls (D2Win.#10024), INPUT_HandleMenuMouseInput (0x180F0), INPUT_HandleMenuKeyDownInput (0x182A0), INPUT_HandleMenuKeyCharInput (0x18370). | Function: MENUS_DrawRegisteredControls Address: D2Win.#10024 ... INPUT_HandleMenuMouseInput D2Win.0x180F0", "source": ["discord:phrozen_code msg 1159313680467501118"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Win.#10024 / 0x180F0 / 0x182A0 / 0x18370"} {"id": "struct.CharScreenStringTable_gpCharScreenStringTabl", "kind": "struct", "status": "sourced", "trust": "sourced", "author": "Silvermane (phrozen_code Discord)", "module": "D2Client", "desc": "Char/stat-screen string layout table array at D2Client.6FB78010. Struct: int nXstart, int nY, int nXend, short nString, int nArg. Governs stat-panel text positioning. | //D2Client.6FB78010 CharScreenStringTable gpCharScreenStringTable[] ... struct CharScreenStringTable { int nXstart; int nY; int nXend; short nString; ", "source": ["discord:phrozen_code msg 1221262234353930240"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.6FB78010"} {"id": "corpus.Stat_screen_click_handlers", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Conqueror (phrozen_code Discord)", "module": "D2Client", "desc": "INTERFACE_StatScreenClickDown (D2Client.0x31290) and INTERFACE_StatScreenClickUp (0x31470), both void __stdcall(D2WinMsgStrc*). Handle input on the character/stat side panel. | Function: INTERFACE_StatScreenClickDown Adress: D2Client.0x31290 ... INTERFACE_StatScreenClickUp Adress: D2Client.0x31470", "source": ["discord:phrozen_code msg 1221313028721606797"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "0x31290 / 0x31470"} {"id": "corpus.Loot_filter_dropped_item_render_handler_hook", "kind": "note", "status": "sourced", "trust": "sourced", "author": "Eggsy (phrozen_code Discord)", "module": "D2Client", "desc": "D2Tweaks hooks two D2Client call sites: +0x1641B = handle dropped items, +0x81BF5 = draw dropped item names (the ground-label render call). Useful anchors for the ground-item name draw in the play area. | m_draw_dropped_items_names_original = ... get_call(diablo2::d2_client::get_base() + 0x81BF5)); ... set_call(...get_base() + 0x1641B, handle_dropped_it", "source": ["discord:phrozen_code msg 1226713514748678186"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "base+0x1641B (handle_dropped_items), base+0x81BF5 (draw_dropped_items_names)"} {"id": "corpus.D2GFX_prevent_minimize_stay_running_unfocuse", "kind": "note", "status": "sourced", "trust": "sourced", "author": "Silvermane (phrozen_code Discord)", "module": "D2GFX/D2Win", "desc": "For windowed/background running: NOP D2GFX 0x4D11 and 0x4932 (VA 6FA74932/6FA74D11) to prevent minimizing; NOP D2Win 0xDC9E (6F8ADC9E) to keep the game running while unfocused. D2Gfx multiclient fix at d2Gfx+0x446A (write 0xEB). | //D2GFX.6FA74932/6FA74D11 prevent minimizing { D2DLL_D2GFX, 0x4D11, 0x90, FALSE, 11 }, { D2DLL_D2GFX, 0x4932, 0x90, FALSE, 11 }, //D2Win.6F8ADC9E Stay", "source": ["discord:phrozen_code msg 1213339683367424081"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2GFX 0x4932 & 0x4D11; D2Win 0xDC9E"} {"id": "struct.D2RoomStrc", "kind": "struct", "status": "sourced", "trust": "sourced", "author": "Silvermane (phrozen_code Discord)", "module": "D2Common", "desc": "Full room struct layout -- the world floor/tile geometry a floor renderer walks. nSubtileX 0x00, nSubtileY 0x04, nSubtileWidth 0x08, nSubtileHeight 0x0C, nTileXPos 0x10, nTileYPos 0x14, nTileWidth 0x18, nTileHeight 0x1C; pRoomTiles 0x20; ppRoomList 0x24; nNumRooms 0x28; pUnitFirst 0x2C; pUnitUpdate 0x30; pCollisionGrid 0x34; pRoomEx 0x38; pSeed 0x3C; dwFlags 0x48; ppClients 0x4C; nTileCount 0x58; pAct 0x78; pRoomNext | int nSubtileX;//0x00 ... int nTileXPos;//0x10 ... D2RoomCollisionGridStrc* pCollisionGrid;//0x34", "source": ["discord:phrozen_code msg 1229965676165337209"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "sizeof ~0x80"} {"id": "struct.item_bounds_check_inventory_grid_pos", "kind": "struct", "status": "sourced", "trust": "sourced", "author": "Eggsy (phrozen_code Discord)", "module": "D2Common", "desc": "Disassembly of D2Common.0x6F68D570 charm-requirement/inventory-slot bounds check. pItem is [ESP+4]; pItem->pDynamicPath/pStaticPath union at +0x2C; grid posX at pPath+0x0C; posY at pPath+0x10. This is the inventory PANEL grid coordinate model used by CharmZone. | 6F68D57B . 8B40 2C MOV EAX,DWORD PTR DS:[EAX+2C] ; pitem->pPath ... CMP DWORD PTR DS:[EAX+0C],5 ; pPath->posX", "source": ["discord:phrozen_code msg 1227993924258365511"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "pItem->pPath at +0x2C; pPath->posX +0x0C; pPath->posY +0x10"} {"id": "corpus.Mana_Health_orb_DC6_size", "kind": "global", "status": "sourced", "trust": "sourced", "author": "Eggsy (phrozen_code Discord)", "module": "D2Client", "desc": "MOV EBX,50 instructions that set the DC6 sprite draw size for the mana and health globes; patch target to enlarge the orb bubbles. | 6FAFFB8B BB 50000000 MOV EBX,50 ; Mana DC6 size ... 6FAFF9F9 ... ; Health DC6 size", "source": ["discord:phrozen_code msg 1230349027871166484"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FAFFB8B (mana), 0x6FAFF9F9 (health)"} {"id": "corpus.light_radius_clamp_sites", "kind": "global", "status": "sourced", "trust": "sourced", "author": "Eggsy (phrozen_code Discord)", "module": "D2Client", "desc": "Four+ CMP/MOV sites that clamp the light radius (CMP EBP,imm / MOV EBP,imm). Patching the immediate (e.g. to 0x1F) forces a large on-screen lit radius regardless of torch/quest state. Verified working in olly. | 6FAA4293 83FD 1F CMP EBP,1F ... 6FAA4298 BD 1F000000 MOV EBP,1F ... This works perfectly", "source": ["discord:phrozen_code msg 1231013221104746506"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "0x6FAA4293, 0x6FAA43A4, 0x6FAA43E7, 0x6FAA4413, 0x6FACD3C3, 0x6FACCC9C"} {"id": "corpus.text_draw_mode_color_site", "kind": "global", "status": "sourced", "trust": "sourced", "author": "Inhuman (phrozen_code Discord)", "module": "D2Win", "desc": "PUSH 4 that supplies the draw-mode/color index for first-line text; color index 9 = white, another index = gold. | 6F8EFA43 6A 04 PUSH 4 ; draw mode first line texts 9 is for white which number is for gold", "source": ["discord:phrozen_code msg 1235440924452982874"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Win.0x6F8EFA43"} {"id": "corpus.prevent_minimize_stay_running_unfocused", "kind": "global", "status": "sourced", "trust": "sourced", "author": "Silvermane (phrozen_code Discord)", "module": "D2GFX", "desc": "NOP these (11 bytes at each D2GFX site, 24 bytes at D2Win site) to stop the game minimizing on focus loss and keep it running while unfocused. | //D2GFX.6FA74932/6FA74D11 prevent minimizing ... //D2Win.6F8ADC9E Stays running while unfocused", "source": ["discord:phrozen_code msg 1227618124623249438"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2GFX.0x4D11 & 0x4932; D2Win.0xDC9E"} {"id": "corpus.INTERFACE_InventoryLButtonDown_UP_1_13c", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Conqueror (phrozen_code Discord)", "module": "D2Client", "desc": "1.13c inventory-panel left-button handlers, __stdcall taking D2WinMsgStrc*. (1.10 equivalents: down 0x46E60, up 0x48140, InteractClickItem 0x475C0.) | D2FUNC(D2CLIENT, INTERFACE_InventoryLButtonDown, ... 0x98DC0) ... INTERFACE_InventoryLButtonUP ... 0x9C630)", "source": ["discord:phrozen_code msg 1229551159417507910"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x98DC0 (down), 0x9C630 (up)"} {"id": "corpus.gbCursorItem_SelectedInvItem", "kind": "global", "status": "sourced", "trust": "sourced", "author": "Neddles (phrozen_code Discord)", "module": "D2Client", "desc": "Global UnitAny* for the item currently held on the cursor / selected in inventory (1.13c). | VARPTR(D2CLIENT, SelectedInvItem, UnitAny*, 0x11BC38) // Updated 1.13c", "source": ["discord:phrozen_code msg 1229553658920702083"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x11BC38"} {"id": "corpus.hovered_item_GUID_accessor", "kind": "global", "status": "sourced", "trust": "sourced", "author": "X_Dan_X (phrozen_code Discord)", "module": "D2Client", "desc": "Used to read the hovered inventory item's GUID (only works for inventory items; user seeking equivalent for chest/stash object units). | I use d2client 0x1158F4 to get the hovered item's guid, but that is for inventory items", "source": ["discord:phrozen_code msg 1235294601082830878"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x1158F4"} {"id": "corpus.ShiftClickStats_character_panel", "kind": "global", "status": "sourced", "trust": "sourced", "author": "Silvermane (phrozen_code Discord)", "module": "D2Client", "desc": "Hook site for the character-screen shift-click stat allocation; patched to cap shift-click stat input at 5. | //Shift clicking only imputs 5 { D2DLL_D2CLIENT, 0x315D3, (DWORD)PATCH_JMP, FALSE, 0x01 }", "source": ["discord:phrozen_code msg 1227616894979407932"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x315D3"} {"id": "corpus.DUNGEON_GetLevelIdFromRoom", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Rayveen (phrozen_code Discord)", "module": "D2Common", "desc": "BYTE __stdcall taking D2RoomStrc*; returns the level id for a room. Pair with UNITS_GetRoom to get the level a unit is standing in. | //D2Common.0x6FD8C7A0 (#10057) BYTE __stdcall DUNGEON_GetLevelIdFromRoom(D2RoomStrc* pRoom)", "source": ["discord:phrozen_code msg 1229473364536463431"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Common.0x6FD8C7A0 (#10057)"} {"id": "corpus.UNITS_GetRoom", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Silvermane (phrozen_code Discord)", "module": "D2Common", "desc": "D2RoomStrc* __stdcall taking D2UnitStrc*; returns the room a unit occupies. | //D2Common.0x6FDBE270 (#10342) D2RoomStrc* __stdcall UNITS_GetRoom(D2UnitStrc* pUnit)", "source": ["discord:phrozen_code msg 1229475762864914584"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Common.0x6FDBE270 (#10342)"} {"id": "corpus.D2GAME_GetRoom_6FC52070_DUNGEON_IsRoomInTown", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Rayveen (phrozen_code Discord)", "module": "D2Game", "desc": "D2ActiveRoomStrc* getter at a target X/Y within a unit's room; DUNGEON_IsRoomInTown tests town membership. | D2ActiveRoomStrc* pRoom = D2GAME_GetRoom_6FC52070(UNITS_GetRoom(pUnit), nTargetX, nTargetY);", "source": ["discord:phrozen_code msg 1234648049272225855"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Game.0x6FC52070"} {"id": "corpus.D2Common_CharmRequirements_10840_rewrite", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Silvermane (phrozen_code Discord)", "module": "D2Common", "desc": "CharmZone technique: rewrite of D2Common.#10840 requirement check restricting charms to an inventory sub-rectangle. Returns TRUE only if item is a charm, unit-type UNIT_ITEM, node page NODEPAGE_STORAGE, and pStaticPath->nYPos >= 6 and reqs met. Hooked from both D2Common (0x5FE70) and D2Client (0x4118B). | { D2DLL_D2COMMON, 0x5FE70, (DWORD)PATCH_JMP, FALSE, 0x01 }, { D2DLL_D2COMMON, 0x5FE71, (DWORD)D2Common_CharmRequirements, TRUE, 0x00 }, { D2DLL_D2CLIE", "source": ["discord:phrozen_code msg 1227616546147401860"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "hook D2Common ordinal #10840 at offset 0x5FE70; D2Client hook 0x4118B"} {"id": "corpus.crash_c0000005_at_6F622D97_on_level_entry", "kind": "note", "status": "sourced", "trust": "sourced", "author": "Mike (phrozen_code Discord)", "module": "D2Common", "desc": "Reported intermittent access-violation in D2Common when entering one particular level -- unresolved in this chunk; possibly level/room load related. No fix given. | c0000005 at 6F622D97 01:00021D97 in D2Common.dll ... when entering one level", "source": ["discord:phrozen_code msg 1237743154052993055"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Common.dll 6F622D97 (01:00021D97)"} {"id": "corpus.belt_itemtype_row_check", "kind": "global", "status": "sourced", "trust": "sourced", "author": "Rayveen (phrozen_code Discord)", "module": "D2Client", "desc": "Belt UI row count: CALL D2Common.#10751/#11088 get item type, CMP EAX,13 (row 19 belt), JNZ hides extra rows | CMP EAX,13 ; Check for row 19 (belt itemtype) ... no additional rows is show", "source": ["discord:phrozen_code msg 1259356769218723922"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FB002E1 / 6FAD8DF1 (1.13c)"} {"id": "struct.Collision_Attributes", "kind": "struct", "status": "sourced", "trust": "sourced", "author": "Neddles (phrozen_code Discord)", "module": "", "desc": "Full COLLISION_* bitflag table 0x0001-0x8000 (BlockWalk, BlockLOS, Wall, BlockPlayer, Missile, Player, DeadBody etc.) used in path/tile collision map | #define COLLISION_BLOCKWALK 0x0001 ... #define COLLISION_DEADBODY 0x8000", "source": ["discord:phrozen_code msg 1286150905992970242"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use"} {"id": "corpus.D2GFX_multibox_nop_patch", "kind": "note", "status": "sourced", "trust": "sourced", "author": "Zephyr (phrozen_code Discord)", "module": "D2GFX", "desc": "Multibox patch nops D2GFX window-focus check; 1.13c range 0x21-0x66 | { D2Dll_kD2GFX, 0x21, kPatchNop, 0, 0x66 - 0x21 }", "source": ["discord:phrozen_code msg 1286714925724467361"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2GFX 0x21..0x66 (1.13c) / 0x446C..0x44B5 (older)"} {"id": "corpus.item_durability_desc_ethereal_check", "kind": "global", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Nop JMP at 6FAE2F0E; calls to D2Client.0x6FAE4060 set up the durability desc line | look for the calls to D2Client.0x6FAE4060 which sets up the durability desc line", "source": ["discord:phrozen_code msg 1291066140738715718"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FAE2F0E (1.10); D2Client.0x6FAE4060"} {"id": "corpus.D2GFX_DrawLine", "kind": "global", "status": "sourced", "trust": "sourced", "author": "Ownasaurus (phrozen_code Discord)", "module": "D2 exe / D2GFX", "desc": "D2GFX_DrawLine at exe base + offset 0xF6380; pointer-arith cast (uintptr_t/DWORD) needed, hooks confirmed working | D2GFX_DrawLine = ...(hBaseExe) + 0xF6380 ... confirmed my hooks work now", "source": ["discord:phrozen_code msg 1322597106929893386"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "base+0xF6380 (e.g. 0x004F6380)"} {"id": "corpus.NewAutomapCell_automap_cell_draw", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Ownasaurus (phrozen_code Discord)", "module": "D2Client", "desc": "NewAutomapCell returns pCell; +0x04 nCellNo determines the graphic drawn in the automap cell (asks re lookup table) | pCell(returned by NewAutomapCell)->nCellNo(offset +0x04) is what determines what is drawn in the cell", "source": ["discord:phrozen_code msg 1325272511608389703"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "pCell->nCellNo +0x04"} {"id": "corpus.AUTOMAP_DrawCells", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Lectem (phrozen_code Discord)", "module": "D2Client", "desc": "Automap cell drawing routine | See AUTOMAP_DrawCells 1.10f:0x6FACE230", "source": ["discord:phrozen_code msg 1325273041328148481"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "1.10f:0x6FACE230"} {"id": "struct.AutomapCellTypeInfo", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "Lectem (phrozen_code Discord)", "module": "", "desc": "{ CelFile* pCelFile; RECT tRect; DWORD nOffsetX; DWORD nOffsetY; } - describes an automap cell graphic | struct AutomapCellTypeInfo { CelFile *pCelFile; RECT tRect; DWORD nOffsetX; DWORD nOffsetY; }", "source": ["discord:phrozen_code msg 1325276707745173589"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use"} {"id": "corpus.Lighting_Interception_patch", "kind": "note", "status": "sourced", "trust": "sourced", "author": "timer (phrozen_code Discord)", "module": "D2Client", "desc": "Lighting interception patch; user reports it fails in Act 5 for 1.13c (may need separate act5 patch) | Patch* lightingPatch = new Patch(Call, D2CLIENT, { 0xA9A37, 0x233A7 }, (int)Lighting_Interception, 6)", "source": ["discord:phrozen_code msg 1332189557915123723"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "Call D2CLIENT {0xA9A37, 0x233A7}, 6 bytes"} {"id": "corpus.weather_storm_phase_setter_rain", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Sets phase of a storm: phase 0 no rain, 1 wind-up, 2 rain, 3 wind-down; contains act5 level-id switch feeding snow/weather globals | D2Client.0x6FAA6D40 ... sets the phase of a storm (with phase 2 being the rain phase", "source": ["discord:phrozen_code msg 1336096681657368657"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6FAA6D40 (1.10)"} {"id": "corpus.snow_weather_render_globals_act5", "kind": "note", "status": "sourced", "trust": "sourced", "author": "ascar31 (phrozen_code Discord)", "module": "D2 exe (1.14d)", "desc": "Act5 snow/rain: per-level switch sets weather DAT_007a89d8/dc/9c/c0 params, RNG FUN_00472280, draw via FUN_004f6300(x,0,y,...); seeds from pPlayer->pSeed | i assume the snow is here ... switch(DVar3) { case LEVEL_HARROGATH ... _DAT_007a89dc = 0x2a", "source": ["discord:phrozen_code msg 1336093360607334471"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "DAT_007a89xx globals; FUN_004f6300; FUN_00472280 RNG; 0x476D23"} {"id": "corpus.NPC_tab_index_top_3_bottom_1", "kind": "global", "status": "sourced", "trust": "sourced", "author": "Arolds (phrozen_code Discord)", "module": "D2Client", "desc": "Controls NPC/store tab selection; topmost tab 3, bottom 1 | It's in D2Client.0xE24F8. top most tab is 3. bottom most is 1", "source": ["discord:phrozen_code msg 1369754621001728120"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0xE24F8"} {"id": "corpus.PAL_LoadActData_per_frame_palette_render_ord", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Win / D2Client", "desc": "Act palette load: D2Client sets act palette via D2Win.#10177 PAL_LoadActData(nActPalette) which calls D2Win.0x6F8AE5E0 with pl2/dat pair; to swap palettes load tile palette each frame, then reload units palette AFTER all tiles rendered (optional 3rd call for UI) | load the tile palette each frame ... make a second call ... just after all tiles have been rendered to load the units palette (and UI", "source": ["discord:phrozen_code msg 1389190948633972787"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Win.#10177 (D2Win.0x6F8AE5E0)"} {"id": "struct.VendorTab_array", "kind": "struct", "status": "sourced", "trust": "trusted", "author": "The Esoteric Path (Doug, phrozen_code Discord)", "module": "D2Client", "desc": "Vendor/store tab struct {int x@0;int y@4;short stringId@8;BOOL isSelected@0xA;BOOL isActive@0xE}; array based at D2Client.0xE1178 | struct VendorTab { int x; int y; short stringId; BOOL isSelected; BOOL isActive; }", "source": ["discord:phrozen_code msg 1397638712913039411"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0xE1178 (array); 0xE1186 (1.13c) / 0xD956E (1.10f)"} {"id": "corpus.vendor_tab_access_asm", "kind": "note", "status": "sourced", "trust": "sourced", "author": "Thaison (phrozen_code Discord)", "module": "D2Client", "desc": "Store-tab loop MOV ECX,D2Client.6FB91186 then indexed access [ESP+EAX*4+10] | MOV ECX,D2Client.6FB91186 ... MOV EBP,DWORD PTR SS:[ESP+EAX*4+10]", "source": ["discord:phrozen_code msg 1397647126841790506"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "6FB3F800 MOV ECX,6FB91186"} {"id": "struct.weather_draw_update_globals", "kind": "struct", "status": "sourced", "trust": "sourced", "author": "ascar91 (phrozen_code Discord)", "module": "D2 exe (1.14d)", "desc": "Weather tick decrements timer, re-rolls via FUN_00472280, and draws overlay via FUN_004f6300 with screen-relative offsets DAT_0071146c/711470 | FUN_004f6300(iVar7,0,iVar5,iVar6,0xff,5); return;", "source": ["discord:phrozen_code msg 1336116018430349332"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "DAT_007a8968/89c4/89e4/89e8/8a04; FUN_004f6300(iVar7,0,iVar5,iVar6,0xff,5)"} {"id": "corpus.stash_close_button_Y_pos", "kind": "global", "status": "sourced", "trust": "sourced", "author": "NetMech (phrozen_code Discord)", "module": "D2Client", "desc": "Patch at D2Client+0x9963C adjusts stash-panel close button Y position | {D2DLL_D2CLIENT, 0x9963C, {0xEB}, 0x01}, // Stash close button Y pos", "source": ["discord:phrozen_code msg 1466201380153856043"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2CLIENT 0x9963C ({0xEB})"} {"id": "corpus.spirit_vine_golem_hp_bar_draw", "kind": "function", "status": "sourced", "trust": "sourced", "author": "oli (phrozen_code Discord)", "module": "D2Client", "desc": "Draws HP bar for spirits, vines and golems (shared); monID check inside failed for user | its offset is 6FADB5F0. But it draws hp bar for spirits, vines and golems", "source": ["discord:phrozen_code msg 1487183426900590693"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "1.10f 0x6FADB5F0"} {"id": "corpus.experience_bar_hover_WIN_text_draw", "kind": "function", "status": "sourced", "trust": "sourced", "author": "Conqueror (phrozen_code Discord)", "module": "D2Client", "desc": "Exp-bar popup init: hit-test uses gnScreenWidth/2-0x92..-0x17 and *D2CLIENT_ScreenHeight-0x2b..-0x22, calls WIN_HoverText; waypoint text via WIN_DrawNormalText(text,x,y,color,transTbl) at 0x6fb2610a | Init here D2Client.0x6faffd58 ... gnScreenWidth / 2 + -0x92 <= nMouseXPos ... WIN_DrawNormalText", "source": ["discord:phrozen_code msg 1408202910441017394"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Client.0x6faffd58; WIN_DrawNormalText 0x6fb2610a"} {"id": "struct.StatMonitor", "kind": "struct", "status": "sourced", "trust": "sourced", "author": "Bobi (phrozen_code Discord)", "module": "D2Client", "desc": "{ wchar_t wszDesc[2][30]; DWORD dwStatNo; DWORD dwTimer; DWORD dwColor; BOOL fEnable; } (asks if same in 1.11b/1.13c) | struct StatMonitor { wchar_t wszDesc[2][30]; DWORD dwStatNo; DWORD dwTimer; DWORD dwColor; BOOL fEnable; }", "source": ["discord:phrozen_code msg 1508828262418088089"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use"} {"id": "corpus.unit_palette_PL2_shift", "kind": "note", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Win / D2Client", "desc": "D2Win.#10175 uses pUnit->nGlobalPaletteShift(+0x6C) for the unit's current PL2 shift, taking precedence over D2Client.0x6FAAE3C0; overwrite those calls for custom PL2 shift | D2Win.#10175 which uses pUnit->nGlobalPaletteShift (+6C) ... takes precedence over D2Client.0x6FAAE3C0", "source": ["discord:phrozen_code msg 1515658277185130648"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "D2Win.#10175; pUnit->nGlobalPaletteShift (+0x6C); D2Client.0x6FAAE3C0"} {"id": "corpus.unit_palette_assignment_monsters", "kind": "function", "status": "sourced", "trust": "trusted", "author": "Necrolis (phrozen_code Discord)", "module": "D2Client", "desc": "Unit palette assignment: 0x6FB27A23 begins it, 0x6FB5BFC0 writes palette index into unit draw data; bosses/champions roll random PL2 shift from unit GUID (source of random color shifts) | D2Client.6FB27A23 is the start of the unit palette assignment (D2Client.0x6FB5BFC0 sets the palette index in the units draw data) for monsters", "source": ["discord:phrozen_code msg 1515703725199589437"], "note": "corpus-sourced; addresses may be 1.10f-era -- rebase to 1.13c + verify before use", "locator": "1.10: 6FB27A23 start; D2Client.0x6FB5BFC0 sets palette index; 1.06 0x71FE7; 1.00 0x9BBE7"} {"id": "finding.d2floortileparams_floor_shift", "kind": "finding", "status": "testing", "trust": "trusted", "author": "The Esoteric Path (Discord corpus mine 2026-07-19)", "desc": "CORPUS-CONFIRMED floor-shift mechanism -- converges with finding.floor_shift_internal_to_pass1. The FLOOR is a SEPARATE drawer from walls/roofs (Necrolis: MULTIRES_DrawGroundTiles vs DrawLowerWallTiles/DrawUpperWallTiles/DrawRoofTiles; SwineFlu confirms floor is a distinct recursive fn per Necrolis's reversed code at d2mods.info t=59615). Floor horizontal placement = D2FloorTileParamsStrc @ D2Client+0xEA990 (0x6FB9A990, sizeof 0x44): nScreenPanels(+0x20)=which panels open, pView(+0x24), clip nXMin/Max nYMin/Max(+0x2C..0x38), nViewXOffset(+0x3C = D2Client+0xEA9CC)/nViewYOffset(+0x40). Necrolis: 'anyone chasing the D2DX floor -320 shift should hook the FILL of this struct and watch nScreenPanels -> nViewXOffset.' Struct filled INSIDE the floor path (1.10f fill 0x6FAA3330 -- rebase to 1.13c by xref of writes to +0xEA990). EXPLAINS why our lens fails on the floor: pre-PASS1 hook authors the render ctx (walls read it -> fixed) but nViewXOffset is set LATER internally from nScreenPanels; our ledger's 'nViewXOffset already 0' was a PRE-fill timing error. FIX: hook the struct fill / DrawGroundTiles and zero nViewXOffset (or force nScreenPanels=0 for the floor pass only) so floor matches the unshifted walls. Cull rect = D2RoomCullArgsStrc{pView,pCullingRect,pClientRoom,bTilesOnly} (Necrolis).", "source": ["discord:phrozen_code (Necrolis 526879393868677131 + 539078647253041172; SwineFlu 862314978442084372; Lectem 539057436447997952)", "https://d2mods.info/forum/viewtopic.php?t=59615"], "refs": ["finding.floor_shift_internal_to_pass1", "finding.live_rpm_2026_07_18", "finding.floor_shift_ledger", "finding.screenshiftx_is_floor_shift"]} {"id": "finding.crossverify_2026_07_19", "kind": "reference", "status": "confirmed", "trust": "verified", "author": "The Esoteric Path (cross-verify 2026-07-19)", "desc": "CROSS-VERIFY of all Grimoire addresses vs the on-disk 1.13c DLLs (D2Client 0x6FAB0000-0x6FBE5000, D2gfx ..0x6FAA1000, D2Win 0x6F8E0000, D2Glide 0x6F850000, D2Common 0x6FD50000, D2Game 0x6FC20000, D2CMP 0x6FE10000). 476 addresses / 698 records: 419 (88%) fall in a valid 1.13c module range (222 D2Client code + 117 D2Client data + D2Glide/D2Common/D2gfx/D2Win/D2Game); 57 FLAGGED as outside any 1.13c module = 1.10f-era/wrong. Flagged cluster = corpus.* 0x6FAAxxxx addresses sitting in the GAP between D2gfx (ends 0x6FAA1000) and D2Client (0x6FAB0000) -> they are 1.10f D2Client (lower base). NOTABLY the floor-drawer MULTIRES_DrawGroundTiles 0x6FAA2E60 and tile-setup 0x6FAA3330 ARE FLAGGED 1.10f -> do NOT use for 1.13c; rebase via struct layout + a 1.13c xref/disasm. RULE: any corpus 6FAAxxxx (below 0x6FAB0000) or cross-module-gap address is 1.10f, rebase before use. Assimilation-verification baseline.", "source": ["cross-verify vs C:/Diablo II/*.dll (1.13c)"], "refs": ["finding.d2floortileparams_floor_shift", "protocol.evidence_rule"]} {"id": "finding.floor_shift_is_ctx_scrollx", "kind": "finding", "status": "confirmed", "trust": "verified", "author": "The Esoteric Path (5-front disasm assault 2026-07-19, direct from 1.13c D2Client.dll)", "desc": "ROOT CAUSE PINNED. The floor+roof static -320 shift is ctx[+0x24] (scrollX), NOT ctx[+0x04] and NOT any global we ruled out. TWO PROJECTION FAMILIES: (1) FLOOR+ROOF flush @0x6FB4ED50 (D2Client+0x9ED50): screenX = ctx[+0x04](drawL) - ctx[+0x24](scrollX) + tileAbsX -- NO offX term. (2) WALLS+UNITS project via offX=ScreenXShift 0x6FBCC418 (RVA 0x11C418) which our lens zeroes -> they re-center. ctx = *0x6FBCC3C4 (RVA 0x11C3C4) = the SAME struct the lens writes (confirmed: both callers of tile drawer 0x6FB4EC10 -- 0x6FB3B224 in PASS2 + 0x6FB4EE7A -- push edi=ctx; PASS1 0x6FB3B0C0->DrawRooms 0x6FB2A9F0 on same ctx). So ctx[+0x04]=0 DOES reach the floor -> not the residual. THE 320 ENTERS ctx[+0x24] at DrawGame 0x6FAF4230: scrollX = scrollCenterX(thunk 0x6FABC1D2 on view *0x6FBCBBFC=playerBase) - (R-L)/2 (0x6FAF4270-79), written 0x6FAF42F8 'mov [esi+0x24],ecx' (esi=*0x6FBCC3C4) right before PASS1 call 0x6FAF4302. Lens moves ctx[+0x04]/[+0x0C] SYMMETRICALLY (-320,960->0,1280) so R-L stays 1280, (R-L)/2 stays 640, scrollX UNAFFECTED -> panel camera re-center +DispW/4=320 survives in ctx[+0x24]. Floor pan = 0-(scrollX_nopanel+320) = static -320. DispW/4=1280/4=320. Roof same path. SUPERSEDES finding.screenshiftx_is_floor_shift, finding.survey_floor_is_downstream, finding.d2floortileparams_floor_shift (that struct was 1.10f). FIX: correct ctx[+0x24] to hold no-panel pan before PASS1 (extend lens; ctx[+0x24]-=DispW/4 for open-panel side, sign per ScreenOpenMode 0x6FBCC414). Floor+roof only. Confirm sign/magnitude via one live RPM of ctx[+0x24] panel-open vs closed standing still.", "source": ["disasm assault vs C:/Diablo II/D2Client.dll (1.13c): 0x6FB4ED50 0x6FB4EC10 0x6FAF4230 0x6FAF42F8 0x6FB3B110 0x6FB2A9F0"], "refs": ["finding.floor_shift_internal_to_pass1", "finding.live_rpm_2026_07_18", "finding.d2floortileparams_floor_shift", "struct.D2Client_RenderContext"]} {"id": "finding.floor_shift_sgd2_tileculling", "kind": "finding", "status": "confirmed", "trust": "verified", "author": "The Esoteric Path (live disasm 2026-07-19, SGD2FreeRes.dll in the running process)", "desc": "DEFINITIVE ROOT CAUSE of the floor/roof panel-shift. It is in SGD2FreeRes.dll (loaded @0x739C0000), NOT D2Client -- D2Client's whole floor path is 100% VANILLA (verified by live-vs-disk patch map: DrawGame 0x44230, scroll write 0x442F8, floor flush 0x9ED50, floor drawer 0x9EC10, DrawRooms 0x7A9F0, PASS1 0x8B0C0, PASS2 0x8B110 all byte-identical to disk). SGD2FreeRes hijacks SetTileCullingBound: D2Client+0x8A4D0 is patched 'jmp 0x739C16B0' (trampoline) -> real fn 0x739D21D0. Inside 0x739D21D0 a PANEL-CONDITIONAL block: 0x739D2212 call 0x739D64A0 (nonzero when a side panel open); 0x739D221A je 0x739D2230 (skip if none); 0x739D221C add [ebx+4],0xFFFFFF60 (top-=160); 0x739D2223 add [ebx],0xFFFFFEC0 (LEFT-=320=DispW/4=0x140); 0x739D2229 add [ebx+8],0x140 (RIGHT+=320). ebx = the tile-cull/draw window (arg+0x14). => on panel-open SGD2 moves the floor's tile window by +/-320. The vanilla flush (screenX = ctx+0x04 - ctx+0x24 + tileAbsX) then faithfully draws the shifted tiles; walls read offX (our lens holds 0) so they don't move -> floor vs walls split by 320. RECONCILES the paradox that render ctx (drawL/scrollX) measured FLAT open-vs-closed (floor_scan same-position: both drawL=0 scrollX=-208, delta 0): the shift rides in tileAbsX collected from the shifted cull window, NOT in the ctx. Other SGD2 hooks confirmed live: SetScreenShift 0xC39F6 -> 0x739D1F80; DrawScreenBg 0xC3AA6 -> 0x739C10B0; stock left/right bg NOP'd @0x271ED/0x270F1. FIX target: neutralize/adjust the panel block at 0x739D221C or its gate je@0x739D221A (NOP-test flips je->jmp). CONFIRMED SHIFT (Doug's 3 screenshots: no-panel centered, inventory=world pushed left, character=pushed right).", "source": ["live disasm SGD2FreeRes.dll @0x739D21D0 (Game.exe PID 17412)", "live-vs-disk patch map of D2Client (scratchpad live_patch_map.py)"], "refs": ["finding.floor_shift_is_ctx_scrollx", "finding.d2floortileparams_floor_shift", "finding.live_patch_map_method", "finding.sgd2freeres_deadzone_architecture"]} {"id": "finding.live_patch_map_method", "kind": "reference", "status": "confirmed", "trust": "verified", "author": "The Esoteric Path (Doug insight + method 2026-07-19)", "desc": "METHOD (Doug's key correction 2026-07-19): the ON-DISK DLL is NOT what runs. PlugY / SGD2FreeRes / d2fps patch D2Client in memory at load; at least 3 mods control frame/UI. Analyzing on-disk VANILLA code produced FOUR dead-end floor-shift hypotheses (see finding.floor_shift_ledger). Correct approach: (1) LIVE-vs-DISK byte diff of the running process reveals every mod patch; (2) disassemble the LIVE (patched) code, following mod redirects; (3) NOP-test via WriteProcessMemory (reversible, elevated) to isolate which mod's patch drives a symptom. D2Client live map: 117 patched regions / 1419 bytes; core floor draw all vanilla; render-controlling mods = SGD2FreeRes (@0x739C0000: SetScreenShift/SetTileCullingBound/DrawScreenBg/disable-stock-bg), PlugY (many), esoteric (ours). Redirect target bases seen: 0x739Cxxxx=SGD2FreeRes; 0x72Exxxx/0x73Dxxxx = mod code; 0x032xxxxx=codecaves(ours); 0x10000000=another module. TOOLKIT built tonight (scratchpad, all elevated RPM/WPM, no x32dbg needed for read/write/NOP): rpm_poll.py, freeze_poke.py, panel_delta.py, floor_scan.py, live_patch_map.py, disasm_sgd2.py, patch_toggle.py.", "source": ["scratchpad live_patch_map.py vs C:/Diablo II/*.dll"], "refs": ["finding.floor_shift_sgd2_tileculling", "finding.floor_shift_ledger"]} {"id": "finding.floor_shift_ledger_v2", "kind": "finding", "status": "confirmed", "trust": "verified", "author": "The Esoteric Path (attempt/failure ledger 2026-07-19)", "desc": "FLOOR-SHIFT HYPOTHESIS LEDGER (chain of superseded theories, each with why it fell): (a) ScreenShiftX D2Client+0x11B9A0 -- FALSIFIED live (WriteProcessMemory froze it to 0, floor did not move; only a border flickered). (b) 'D2DX shifts floor-category downstream' -- FALSIFIED by reading bolrog+Necrolis D2DX source (NO per-category transform; only uniform UnitMotionPrediction, and nomotionprediction=true gave no change). (c) D2FloorTileParamsStrc.nViewXOffset @0x6FB9A990/0x6FB9A9CC -- FALSIFIED: that instance address is 1.10f, ZERO refs in our 1.13c DLL (xref + immediate byte-search); the struct LAYOUT transfers but the 1.13c instance differs. (d) 'ctx+0x24 scrollX carries +320' (5-front on-disk disasm assault) -- FALSIFIED live: floor_scan same-position closed-vs-open showed drawL=0/scrollX=-208 in BOTH (delta 0). (e) CONFIRMED: SGD2FreeRes SetTileCullingBound live patch shifts the tile-cull window +/-320 on panel-open (finding.floor_shift_sgd2_tileculling). META-LESSON: (a)-(d) all came from analyzing the ON-DISK vanilla DLL. The shift is in a MOD's live patch. Doug flagged the layered-mod interaction; the live-vs-disk patch map resolved it. Also: a same-position live read (stand still) is required -- 20-min-apart readings are confounded by camera movement.", "source": ["live RPM/WPM session 2026-07-19"], "refs": ["finding.floor_shift_sgd2_tileculling", "finding.live_patch_map_method", "finding.floor_shift_ledger", "protocol.evidence_rule"]} {"id": "finding.freeze_scrollx_flush_live", "kind": "finding", "status": "confirmed", "trust": "verified", "author": "The Esoteric Path (live WPM freeze test 2026-07-19, Doug visual+screenshot)", "desc": "FREEZE-scrollX TEST (hammered ctx+0x24 = *(D2Client+0x11C3C4)+0x24 from -240 to -600, 3439 writes/30s): BOTH floor AND walls flickered/slid (Doug: 'a lot of flickering on the walls and floors'). CONCLUSIONS: (1) the D2Client flush 0x6FB4ED50 / render-ctx path IS the LIVE world render -- SGD2FreeRes does NOT draw the floor via its own renderer; the vanilla screenX = ctx+0x04(drawL) - ctx+0x24(scrollX) + tileAbsX is what shows. Rules IN the D2Client path. (2) CORRECTS finding.floor_shift_is_ctx_scrollx: walls do NOT use offX-not-scrollX -- BOTH floor and walls read ctx+0x24. The world renders as a unit through this ctx. (3) By elimination: drawL+scrollX are FLAT panel-open-vs-closed (floor_scan same-position delta 0), the flush is live, so the panel shift can only ride in tileAbsX (the COLLECTED tile coords). Leading theory: our no-shift lens forces drawL=0 AFTER DrawRooms already collected tiles using the game's shifted drawL (the council-wave-6 'hook too late'). ALSO: NOP of SGD2 SetTileCullingBound panel-block (0x739D221C) had ZERO impact -> that cull-widen is not the shift. NEXT: read tileAbsX/screenX at the flush (codecave probe or hardware BP) panel-open vs closed; and re-check WHEN our lens sets drawL vs when DrawRooms reads it.", "source": ["live WPM freeze ctx+0x24 (Game.exe PID 17412, ctx 0x214639D4)"], "refs": ["finding.floor_shift_is_ctx_scrollx", "finding.floor_shift_sgd2_tileculling", "finding.floor_shift_internal_to_pass1", "finding.floor_shift_ledger_v2"]} {"id": "finding.floor_shift_measured_320", "kind": "finding", "status": "confirmed", "trust": "verified", "author": "The Esoteric Path (Doug's waypoint experiment + template-match 2026-07-19)", "desc": "OBJECTIVE PIXEL-PRECISE MEASUREMENT of the floor shift. Setup (Doug): Barbarian standing on the Act1 encampment waypoint, no merc, no effects. The waypoint = co-located FLOOR marker (brown cross-diamond) + UNIT markers (blue swirls). Captured game frames closed vs open, template-matched each marker: waypoint brown-cross (FLOOR tile) moved LEFT 480 screen-px (dy 0, conf 0.56); blue swirl (UNIT) 0px (conf 0.82); campfire embers (OBJECT) 0px (conf 0.68); walls 0 (prior overlay). Screen is 1920w upscaled by D2DX from game-render 1280 (DispW) => factor 1.5 => 480 screen-px = 320 GAME-px = exactly DispW/4. DEFINITIVE: the FLOOR-TILE LAYER shifts exactly DispW/4 = 320 game-px LEFT on panel-open; units/objects/walls hold at 0 (offX layer, our lens already fixes them). Confirms Doug's exact claim to the pixel. RECONCILES the whole investigation: the render ctx (drawL/scrollX) reads FLAT open-vs-closed because the 320 rides in the collected floor tileAbsX, NOT the camera scalars; the earlier full-floor overlay aliased the 320 (=~5 tiles) but the waypoint's non-periodic cross revealed it. Method note: capture the game window via PIL ImageGrab (D2DX/D3D content grabs fine); measure in GAME-space = screen/1.5. FIX TARGET: un-shift the floor tile collection (tileAbsX) by DispW/4. Ruled out as the source: ScreenShiftX 0x11B9A0 (poke null), SGD2 SetTileCullingBound cull-block 0x739D221C (NOP null), the render ctx (flat). It is in the floor tile-coordinate computation (DrawRooms / the floor pass tileAbsX).", "source": ["game-frame capture + template-match (wp_closed.png/wp_open.png, Game.exe PID 17412)"], "refs": ["finding.freeze_scrollx_flush_live", "finding.floor_shift_ledger_v2", "finding.floor_shift_internal_to_pass1", "finding.floor_shift_sgd2_tileculling"]} {"id":"finding.survey_minmax_aliasing_blind","kind":"finding","date":"2026-07-19","title":"SURVEY/phase-corr min-max envelope is BLIND to a sub-tile-period floor shift","body":"The [SURVEY] probe (grDrawVertexArrayContiguous vertex X min/max, closed vs open) reported dMinX=0 for the floor caller 0x6A55 (x=-32..1296 both states), which I nearly read as 'floor reaches the GPU unshifted'. WRONG: the floor is a periodic full-screen tile grid; a -320 (=DispW/4) shift REFILLS the same min/max envelope, so the envelope is invariant under the exact shift Doug sees. Same aliasing trap that made diff_shift.py phase-correlation return dx=0 on the floor grid. RULE: never use a min/max envelope or a periodic-signal correlation to decide whether a tiled floor shifted; use a NON-periodic landmark (Doug's waypoint template-match gave the true -320) or read a specific tile's abs coord. Doug's direct visual observation (floor+waypoint slide -320, units/walls hold) stands; the probe simply cannot see it.","refs":["finding.floor_shift_measured_320","probe.glidevtx","diag.diff_shift_aliasing"]} {"id":"finding.floor_shift_root_ctxl_prologue","kind":"finding","date":"2026-07-19","title":"Floor -320 is baked into tile coords in the DrawGame PROLOGUE via native ctxL=-320, before the lens's PASS1-hook correction","body":"Live [NOSHIFT] log (session PID17412, right panel mode=1): ctxL -320->0 every frame -- the native game sets ctx+0x04 (draw-window left) = -DispW/4 = -320 on right-panel-open, and the NoShift lens zeroes it at the PASS1-call hook 0x6FAF4302. But the floor room-collection reads ctxL a beat EARLIER (DrawGame prologue, before the hook; council-wave-6 note feature_panelworld.c:590), so the -320 is baked into the collected tile abs coords (tileAbsX); the flush 0x6FB4ED50 (screenX=ctxL-scrollX+tileAbsX) then faithfully carries it with ctxL=0. offX held 0 (units/walls safe); ctxL NOT held early enough for the floor. [FLOORPARAMS]/[SCRATCH] channels empty => nViewXOffset & scratch-scroll are NOT the carrier; ctxL-baked-in-prologue is. Source of the -320: view-setup fn 0x6FB29140 computes -DispW/4 and writes it to ctx+0x04 via cull-bound setter 0x6FB3A4D0 (pass-through). TEST IN FLIGHT: esoteric.ini FloorCompX=320 + glidevtx floor-filter 0x6840 -> compensate the floor's vertex X +320 at the D2Glide submit; if the floor snaps into alignment, upstream-baked confirmed and the root fix = author ctxL=0 before the prologue collection (earlier hook) or NOP the 0x6FB29140 -320 write.","refs":["finding.survey_minmax_aliasing_blind","finding.floor_shift_measured_320","sym.cullbound_setter_6FB3A4D0","sym.viewsetup_6FB29140","feature.floorcompx"]} {"id":"finding.floor_draw_path_DEFINITIVE","kind":"finding","date":"2026-07-19","title":"DEFINITIVE floor draw path: D2Glide 0xB890 via grDrawVertexArray@12; -320 baked in vertex screen-X upstream","body":"Settled by LIVE execution counters (safe codecave, no guessing): (1) The floor is drawn by D2Glide fn 0x6F85B890 (an FPU polygon rasterizer) via grDrawVertexArray@12 (thunk 0x6F856026 -> IAT 0x6F861250). @12 fires ~54k calls/2s, ONLY from 0xB890 (call sites 0xBC57/0xBEF7). (2) The workflow's 0x6F856290 AND 0x6F856AA0 (both have the pretty DispW/4+neg -320 logic and call @12) are DEAD -- entry execution counters = 0 while walls_6840 counter = 310969. Patching either's mode-1 cmp (0x62B8 / 0x6AC9 : 01->7f) did NOTHING (confirms dead; corroborates the old v1.9.1 KB 'dead 0x6290'). The live dispatch calls 0x6AA0 from 0x8572B2 but 0x6AA0 still never executes -- 'called-from' != 'executed'. (3) Walls are @16 grDrawVertexArrayContiguous (IAT 0x6F8611D0) via 0x6840; the 4 probed callers 0x6A55/0xA344/0x9AF4/0xA555 are ALL @16 (walls) -- which is why FloorCompX on 0x6A55 moved walls not floor (wrong primitive). (4) The @12 vertices are an array of POINTERS (arg3=0x6F866308 -> ptrs 0x6F865F18..) into 0xB890's OWN static scratch buffer at D2Glide 0x6F865F18 (0xB890 opens with 'mov edi,0x6f865f18'); that buffer is READWRITE and holds REAL screen coords (captured GrVertex X=720.0 Y=164.0, 7 floats/28B stride, panel open). So the floor's -320 is baked into the vertex SCREEN-X and rides from D2Client through D2Glide unchanged; 0xB890 and its callers 0xD1A0<-0xDF4F compute NO DispW/4 (the DispW touches there are RGB565 unpack + res-config writes 0x280/0x320). CONCLUSION: the -320 is baked ONCE upstream in D2Client's floor tile abs-coord (tileAbsX at flush 0x6FB4ED50), in a value the NoShift lens does NOT touch (not ctxL/offX/nViewXOffset -- holding all three 0 never moved the floor). The aliasing-blind [SHIFT]/[SURVEY] probes (min/max envelope on a periodic tile grid) could not see it. FIX MUST BE UPSTREAM (static patch), NOT a live per-vertex comp: 3 ACCESS_VIOLATION crashes came from hand-writing the shared 450x/frame vertex buffer live (FPU/accumulation/downstream-D2DX-fragility). Live toolkit built this session: log_drawers.py (entry exec counter+mode histogram, codecave), iat_count.py (draw-primitive call counter), safe_at12_log.py (READ-ONLY arg capture), patch_dg_byte.py (1-byte D2Glide patch). Codecave lesson: stub must NOT overlap its own data buffers; rel8/rel32 = target-(end of jump); verify-disasm-before-fire catches bugs.","refs":["finding.survey_minmax_aliasing_blind","finding.floor_shift_root_ctxl_prologue","finding.floor_shift_measured_320","sym.d2glide_floor_drawer_B890","sym.d2glide_wall_drawer_6840"]} {"id":"finding.d2client_flush_6FB4ED50_DEAD","kind":"finding","date":"2026-07-19","title":"D2Client tile flush 0x6FB4ED50 is DEAD -- the floor's live screen-X exists ONLY in the D2Glide @12 vertex buffer","body":"Read-only exec probe at the flush 0x6FB4ED6E (cmp bl,0xff): with the game IN-GAME (worldCtx 0x21FD39D4) and the RIGHT panel open (ScreenOpenMode=1) and the hook confirmed installed (byte 0xE9), the flush counter stayed idx=0 -- it NEVER FIRES. So the tile flush screenX=ctxL-scrollX+tileAbsX @0x6FB4ED50 (the projection the NoShift lens PW_RVA_FLUSHHOOK and the floor-path workflow both analyzed) is DEAD CODE. This is why holding ctxL/offX/nViewXOffset=0 never moved the floor: they feed a dead projection. SAME dead-code trap as the D2Glide twins 0x6290/0x6AA0. CONSEQUENCE: there is NO live D2Client static-patch point of the classic form; the floor's finalized screen coordinate exists ONLY in the D2Glide @12 vertex buffer (0xB890 output at D2Glide 0x6F865F18, GrVertex X=720 panel-open, READWRITE). Likely the vanilla D2Client tile path was redirected by SGD2FreeRes (d2dx_sgd2freeres.dll, the res+sidebar mod that also owns SetTileCullingBound 0x739D221C LEFT-=320/RIGHT+=320) into the D2Glide 0xB890/@12 path, and the -320 sidebar shift is applied on that live path -- NOT in vanilla D2Client. PRAGMATIC FIX: a +320 comp on the @12 (grDrawVertexArray, IAT 0x6F861250) floor vertices, done in crash-tested C in esoteric.dll (masked FPU, skip NaN/inf, gate ScreenOpenMode==1) -- targets the floor primitive only (walls=@16). Live hand-rolled per-vertex comp crashed (ACCESS_VIOLATION) 3x: read-only capture PROVED the vertices are pointer-array into a READWRITE static buffer refilled per-call (no accumulation) with real coords, so the crash was FPU-on-special-value or a downstream D2DX effect from the shifted X -- both handled by the framework's C path. ROOT (deeper): trace 0xB890 coord source or SGD2FreeRes's floor redirect.","refs":["finding.floor_draw_path_DEFINITIVE","finding.survey_minmax_aliasing_blind"]} {"id":"finding.floor_at12_CONFIRMED_shear","kind":"finding","date":"2026-07-19","title":"@12 CONFIRMED as the live floor path (Doug visual); +320 vertex comp SHEARS the floor (shared-vertex mesh)","body":"BREAKTHROUGH: v1.13 comps the floor's grDrawVertexArray@12 vertex X (+320 right panel, in crash-safe C, retaddr-filtered to 0xB890's submits [0xBC00,0xBF00)). Doug's DIRECT visual confirmation: the comp VISIBLY affects the FLOOR ('you are ABSOLUTELY touching the right place now') -- units/walls unaffected. So @12 / D2Glide 0xB890 IS the live floor draw, settled beyond doubt after a session of dead-code traps (0x6290/0x6AA0 @12 twins dead, D2Client flush 0x6FB4ED50 dead). NEW SYMPTOM: instead of a clean +320 translate, the floor renders DISTORTED/SHEARED (horizontal smear of the ground plane; panel-closed baseline is clean; units undistorted). This matches the safety-review's #1 predicted correctness risk: the floor is a SHARED-VERTEX mesh (grDrawVertexArray@12 = array of POINTERS to GrVertex; D2's isometric floor tiles share edge/corner vertices), so blindly comping every pointer-array entry double-comps shared vertices (+640 on shared, +320 on unique) -> shear. Also possible: the two @12 submit sites in 0xB890 (0xBC57/0xBEF7) reuse the static buffer 0x6F865F18, or per-frame accumulation across the ~450 calls/frame. FIX DIRECTION: comp each UNIQUE vertex exactly once (per-call or per-frame de-dup of vertex pointers), OR shift at a stage upstream of the shared-vertex expansion, OR find where SGD2FreeRes applies the sidebar shift and neutralize it there. Crash-safety now solid (integer NaN/Inf exponent check before any x87 fld -- the review caught that the earlier fld-on-SNaN was the same bug as the 3 asm crashes). Next: research the D2 floor mesh structure + SGD2FreeRes sidebar shift + D2DX grDrawVertexArray, then a shear-free comp.","refs":["finding.floor_draw_path_DEFINITIVE","finding.d2client_flush_6FB4ED50_DEAD"]} {"id": "attempt.floor_at12_dedup_v1", "kind": "attempt", "date": "2026-07-19", "title": "@12 floor comp de-dup: comp each UNIQUE vertex pointer once per call (shear fix, perspective OFF confirmed)", "body": "Doug confirmed he does NOT play with D2 'Perspective' video mode on -> the floor is orthographic, so a FLAT +320 comp is geometrically valid (no per-Y scaling), which makes the shared-vertex de-dup the correct fix for the shear (finding.floor_at12_CONFIRMED_shear). CHANGE (src/probe.c, PK_VTX12 branch): added a per-call seen[256] pointer set; when comp!=0 each vertex POINTER is comped exactly ONCE (linear-scan de-dup, skip duplicates) so shared strip/fan verts get +320 not +640. Crash-safety unchanged (null-ptr skip + integer NaN/Inf exponent check before any x87 fld). Built with portable Zig (tools/build.ps1) + deployed to C:\\Diablo II\\esoteric.dll (264704 bytes, mtime 2026-07-19 20:50). ini armed: FloorCompX=320, glidefloor=vtx12 D2Glide 0x11250 0xBC00, Survey=0. PREDICTION: floor now translates a clean +320 (fills the panel-open dead-zone) WITHOUT the horizontal smear. PENDING: Doug relaunch (PlugY, non-elevated via explorer) + open right panel + report. If it still shears -> either >256 distinct verts/call (raise cap) or the shear is in D2DX's fan expansion downstream (go upstream: write-BP the SGD2FreeRes floor-shift global). CAVEAT: seen cap 256 -> a single @12 call with >256 distinct verts would leave the tail un-de-duped (observed calls ~12 verts, so unlikely).", "refs": ["finding.floor_at12_CONFIRMED_shear", "finding.floor_draw_path_DEFINITIVE"]} {"id": "finding.floor_dedup_v1_FAILED", "kind": "finding", "date": "2026-07-20", "title": "@12 floor de-dup v1.14 FAILED live (still shears); count=12000 is an AGGREGATE not per-call; root cause unconfirmed", "body": "Doug tested attempt.floor_at12_dedup_v1 (v1.14, per-call seen[256] pointer de-dup) LIVE: the ground tiles STILL show significant distortion/smear -- the de-dup did NOT fix the shear. CORRECTION: the probe log '[PROBE glidefloor] count=12000' is p->cnt, an ACCUMULATED counter summed across many floor calls between dumps (probe.c:254), NOT one call; probe.c:91 bails on any call >4096 verts. So per-call vertex count is UNMEASURED (prior single capture ~12 verts). TWO candidate causes, NOT yet distinguished -- do NOT patch on a guess: (a) seen[256] cap too small -> a call with >256 unique verts leaves the tail double-comped -> shear; (b) the >4096-vert bail -> big floor calls skip the comp entirely (render shifted) while small calls render comped -> a MIX that reads as tearing. Need a per-call count measurement (add per-call log, relaunch). Source read confirmed D2DX reads each source pointer ONCE, so the in-place de-dup MODEL is right; the shear is our comp double-hitting shared pointers within the source array. LESSON: my read of Doug's screenshot as 'no shear' was WRONG -- pixels lie, Doug's eyes are ground truth (he caught it).", "refs": ["attempt.floor_at12_dedup_v1", "finding.floor_at12_CONFIRMED_shear"]} {"id": "finding.floor_shift_source_and_disasm", "kind": "finding", "date": "2026-07-20", "title": "Floor -320 = native D2Client width/4 on SGD2FreeRes's 1280, DECOUPLED from offX; D2DX exonerated; scr@0x11C414 + width@0x6FB8BC48", "body": "SOURCE READ (4-agent workflow over refsrc/ SGD2FreeRes + d2dx-jarcho + D2MOO): (1) D2DX EXONERATED -- OnDrawVertexArray reads each floor GrVertex.x ONCE, maps linearly to NDC, no X offset; the -320 is baked in BEFORE D2DX -> the de-dup model is correct. (2) SGD2FreeRes has NO literal width/4 or panel-conditional floor shift; it only sets GeneralDisplayWidth=1280 (native width/4 = 320 vs vanilla 640->160) and ScreenShiftX = width/2-320 = 320. So the floor -320 is NATIVE D2Client re-deriving from width at draw time, AMPLIFIED (1280) + DECOUPLED from units by SGD2FreeRes. (3) D2MOO: vanilla shifts floor+units TOGETHER via one camera origin -> a floor-ONLY divergence is a MOD artifact. LIVE+DISASM (same-user ctypes RPM + capstone on on-disk D2Client, base 0x6FAB0000): scr @ D2Client+0x11C414 (abs 0x6FBCC414) = panel flag, LIVE-CONFIRMED 0->1 on inventory open (2=left). Resolution-WIDTH global = [0x6FB8BC48] (800/640 on disk; SGD2FreeRes patches to 1280 live). Vanilla panel handler @ 0x6FACE8B3 / 0x6FACEA3F: mov eax,[0x6FB8BC48]; cdq; and edx,3; add eax,edx; sar eax,2; neg eax (= -(width/4)) -> mov [0x6FBCC418],eax (offX) ; mov [0x6FBCC414],1 (scr). BUT offX (0x6FBCC418) = UNITS/WALLS shift: live offX read 0 with inventory open yet floor still -320 -> FLOOR IS DECOUPLED from offX (matches ledger_v2). Broad open-vs-closed D2Client memory diff found NO clean stored -320 global (camera drift = noise) -> floor shift is INLINE / a SGD2FreeRes hook. D2FloorTileParamsStrc (code-editing KB, Necrolis): nScreenPanels+20, pView+24, nViewXOffset+3C; instance addr 0x6FB9A990 is a 1.10f addr (0 refs in our 1.13c -> confirms ledger_v2 (c)). VERIFIED STACK: Jarcho d2dx 0.103.4 (glide3x, NOT bolrog -- that's the .bak) writes+loads bundled d2dx_sgd2freeres.dll + d2fps 1.0.2; PlugY 14.03.", "refs": ["finding.floor_dedup_v1_FAILED", "finding.floor_shift_ledger_v2", "finding.floor_shift_measured_320"]} {"id": "finding.floor_re_offload_chatgpt", "kind": "finding", "date": "2026-07-20", "title": "Floor -320 site still unpinned (D2Client inline vs SGD2FreeRes hook); RE offloaded to ChatGPT via FLOOR_RE_PACKAGE", "body": "The floor's exact -320 site is unpinned: either a separate inline -width/4 in the D2Client floor-tile draw loop (gated by scr/nScreenPanels) OR a SGD2FreeRes live patch/hook of that draw. On-disk D2Client search: scr (0x6FBCC414) = 210 refs; filtered to 60 sites reading width AND scr AND computing -(x/4) -- too many to eyeball, and the on-disk floor draw may be vanilla (SGD2FreeRes patches it live). Doug has FREE ChatGPT frontier compute, so the RE is OFFLOADED: assembled FLOOR_RE_PACKAGE_for_ChatGPT.md (esoteric-dll root, ~231KB/56k tok) = findings + DATA A (the 60 D2Client candidate disasm sites, offX handler flagged) + DATA B (SGD2FreeRes D2Client render patches: set_screen_shift / set_tile_culling_bound / set_general_display_width_and_height) + DATA C (D2FloorTileParamsStrc + PATH_WorldToScreen). Asks for the exact site + a minimal version-guarded byte patch (esoteric.dll applies via WPM at load) un-shifting ONLY the floor. AWAITING ChatGPT result -> verify vs live binary -> implement. Toolkit: scratchpad/{live_floor_read,scan_disk,scan_scr_shift,gen_disasm,build_package}.py. OPEN FIX OPTIONS: A=fix the comp (measure per-call count -> hash-set de-dup + handle >4096 calls); B=upstream neutralize (this package).", "refs": ["finding.floor_shift_source_and_disasm", "finding.floor_dedup_v1_FAILED"]} {"id": "finding.floor_shift_site_FOUND_verified", "kind": "finding", "date": "2026-07-20", "title": "FLOOR -320 SITE FOUND + byte-verified: D2Client 0x6FB10275 (scr->EBX=+/-width/4); 2-byte patch 0x6027D 74 15->EB 27", "body": "ChatGPT (frontier, fed FLOOR_RE_PACKAGE) located the floor shift; I VERIFIED it byte-for-byte vs on-disk D2Client. The recursive ground-tile traversal at D2Client 0x6FB10250 (RVA 0x60250) holds the floor-local panel offset: 0x6FB10275 mov eax,[0x6FBCC414](scr); 0x6FB1027A xor ebx,ebx (EBX=0 default); dec eax; 0x6FB1027D je 0x6FB10294 (scr==1 right); dec eax; jne 0x6FB102A6 (scr!=2); scr==2 LEFT -> EBX=+width/4; scr==1 RIGHT @0x6FB10294 -> mov eax,[0x6FB8BC48](width); sar eax,2; mov ebx,eax; neg ebx = -width/4. At 1280 (SGD2FreeRes-patched width) EBX=-320 right/+320 left; applied to tile coords at 0x6FB102A6+ (movsx eax,[ecx+6]; idiv [0x6FBA16B0]; sub edi,[0x6FBCC1F8]). VERIFIED FIX: patch 0x6FB1027D 74 15 (je 0x6FB10294) -> EB 27 (jmp 0x6FB102A6); EBX pre-cleared by the xor, so ALL panel states reach 0x6FB102A6 with EBX=0 -> NO floor shift, no shear, single site. SIGNATURE @RVA 0x6027C = 48 74 15 48 75 24 A1 48 BC B8 6F, confirmed EXACT on the live binary. Untouched: offX(0x6FBCC418 walls/units), panel state, and the culling block @0x6FB10C52/0x6FB10D12 (commits view window to 0x6FBCC1F0/1F4/1F8/1FC -- DO NOT patch that). NOT a SGD2FreeRes hook (it only sets width=1280, magnifying this vanilla /4). Implement via eso_patch_bytes (verify-then-write). Before test: turn OFF the competing FloorCompX comp (=0) + the PanelWorldNoShift/D2DXWiden shift-features so the clean upstream patch is tested alone. PENDING Doug live test.", "refs": ["finding.floor_re_offload_chatgpt", "finding.floor_shift_source_and_disasm"]} {"id": "finding.floor_patch_v115_CONFIRMED_shear_gone", "kind": "finding", "date": "2026-07-20", "title": "FloorPanelShiftFix v1.15 CONFIRMED LIVE: floor shear/divergence GONE (world coherent; whole-world vanilla shift remains, PanelWorld's job)", "body": "esoteric.dll v1.15 applied the verified 2-byte patch (esoteric.log: '[patch] OK floor-panel-shift @ 6FB1027C'). Doug live-tested in ISOLATION (FloorPanelShiftFix=1, PanelWorld=0, D2DXWiden=0, FloorCompX=0): the FLOOR SHEAR IS GONE -- the world renders COHERENT (waypoint diamond sharp, ground moves as one piece); Doug: 'everything is shifted now, as if back to vanilla'. INTERPRETATION: the D2Client 0x6FB10275 EBX=+/-(width/4) branch was the floor's EXTRA/DIVERGENT shift ON TOP of the whole-world camera recenter, NOT the world shift itself. Zeroing EBX makes the floor shift the SAME amount as units/walls -> coherent, no divergence, no shear. The multi-day floor shear/divergence bug is SOLVED. What remains is the whole-world vanilla camera shift (a SEPARATE mechanism -- exactly what PanelWorld's NoShift suppresses). Why PanelWorld sheared before: it held units at 0 while the floor's EBX branch kept diverging; with EBX=0 the floor no longer fights the no-shift lens. NEXT (ini only, no rebuild): re-enabled PanelWorld=1 + D2DXWiden=1 alongside FloorPanelShiftFix=1 -> the no-shift + widen stack should now hold the whole world coherently AND fill behind the panel. Pending Doug relaunch + test.", "refs": ["finding.floor_shift_site_FOUND_verified", "finding.floor_shift_measured_320"]} {"id": "finding.floor_collection_shift_cullblock", "kind": "finding", "date": "2026-07-20", "title": "Floor+roof RESIDUAL shift = tile COLLECTION/cull shift @ D2Client 0x6FB10C52 (EBX=+/-width/4 -> sub ecx,ebx @0x6FB10D12 -> view window 0x6FBCC1F0)", "body": "After the floor DRAW patch (0x6FB1027D, shear gone) + PanelWorld NoShift+Widen+D2DXWiden ALL applying (log 04:37: [NOSHIFT] offX0/ctxL-320->0, [WIDEN] ctx0C 960->1280, D2DXWiden 1280 asserted), Doug: floor AND roof STILL shift. FOUND the source -- a SECOND width/4 shift in the tile VIEW/CULL setup @ D2Client 0x6FB10C52: mov eax,[0x6FBCC414](scr); xor ebx,ebx; dec eax; je 0x6FB10CBC(right); dec eax; je 0x6FB10C91(left); each branch (gated also by ebp=[0x6FBCC1B0]==1) computes EBX=+/-(width/4) from [0x6FB8BC48], then 0x6FB10D12 'sub ecx,ebx' commits to the VIEW WINDOW 0x6FBCC1F0/1F4/1F8/1FC. The ground-tile traversal (0x6FB10250) READS 0x6FBCC1F8 for bounds -> shifts ALL collected tiles (floor+roof) at COLLECTION, BEFORE PanelWorld's NoShift zeroes the camera = the multi-session 'hook too late', now pinned. ChatGPT flagged 0x6FB10C52/0x6FB10D12 as risky (drives tile CULLING/selection) -> un-shifting may clip margins (mitigated by D2DXWiden=1280). This is the DRAW-shift (patched) vs COLLECTION-shift (this) split. Doug has ~unlimited free ChatGPT frontier compute (promo) -> chose to OFFLOAD: package E:\\...\\esoteric-dll\\FLOOR_RE_PACKAGE2_collection_for_ChatGPT.md (context + cull-block disasm + traversal read + question: un-shift collection WITHOUT breaking culling). AWAITING ChatGPT -> verify vs binary -> patch.", "refs": ["finding.floor_patch_v115_CONFIRMED_shear_gone", "finding.floor_shift_site_FOUND_verified"]} {"id": "finding.floor_fix_CONVERGENT_scr_virtualize", "kind": "finding", "date": "2026-07-20", "title": "CONVERGENT ANSWER (4 ChatGPT prompts): virtualize scr(0x11C414)=0 TRANSACTIONALLY around the world pass (PASS1@0x6FAF4302..PASS2@0x6FAF436A); scr is the shared SELECTOR, no single derived shift global", "body": "Ran 4 frontier prompts (forward-RE, architecture-rethink, adversarial-audit, prior-art-research) + 3 KB-extracts. They CONVERGED: there is NO shared derived panelShiftX global; scr @0x6FBCC414 (ScreenOpenMode) is the shared SELECTOR that MULTIPLE INDEPENDENT consumers each read to recompute +/-(width/4) (floor EBX @0x6FB10275, view/cull @0x6FB10C52, others). Clean fix is NOT per-consumer whack-a-mole -- VIRTUALIZE scr=0 for the WORLD RENDER PASS, RESTORE it for the UI/panel draw (D2R does exactly this scene/UI separation). offX(0x11C418) is NOT the root (separate walls/units offset). Prior-art: SGD2FreeRes is the closest legacy prior art (patches CullingSpec draw_window_rect+tile_culling_window); no known LoD mod does full world-under-panel; a wrapper +320 is too late (can't recover un-collected tiles). Audit MISREAD our draw patch as asymmetric -- it's EB=unconditional jmp so ALL scr reach 0x6FB102A6 with EBX=0 (symmetric, re-verified). KEY: PanelWorld ALREADY has a scr=0 hold (g_hold_mode / ini PanelWorldHoldMode, DEFAULT OFF) but as an ASYNC thread holding scr=0 continuously incl. during UI -> 'diamond'/cull artifacts. FIX = TRANSACTIONAL: DrawGame @0x6FAF4249 loads ctx *[0x6FBCC3C4], calls PASS1(0x6FB3B0C0)@0x6FAF4302 then PASS2(0x6FB3B110)@0x6FAF436A(walls/roofs/units); PanelWorld already hooks the PASS1 call (PW_RVA_PASS1CALL 0x44302). Set scr=0 before PASS1, restore after PASS2. QUICK TEST first (ini PanelWorldHoldMode=1, no rebuild): does async scr=0 un-shift the floor (artifacts OK)? If yes -> implement transactional; then ChatGPT's check: reverting 0x6027D/0x6FB10D12 should still compute 0 (scr=0).", "refs": ["finding.floor_collection_shift_cullblock", "finding.floor_shift_persists_render_origin_drawL", "finding.floor_patch_v115_CONFIRMED_shear_gone"]} {"id": "impl.scrguard_v117_built_verified_deployed", "kind": "impl", "date": "2026-07-20", "title": "v1.17 TRANSACTIONAL scr=0 world-pass guard: implemented in PanelWorld, CONFIRMED_SAFE on 3 adversarial angles, built + deployed", "body": "Implemented ChatGPT's transactional guard as pw_install_scrguard() in feature_panelworld.c, gated by [Features] PanelWorldScrGuard. Mechanism: E9-detour the GATE @0x6FAF4243 (6 bytes 0F857501 0000 = jne 0x6FAF43BE) -> 0x80-byte cave entry stub (pushfd/pushad; if depth==0 save scr@0x6FBCC414; depth++; if saved scr in {1,2} set scr=0; popad/popfd; REPRODUCE the original JNE via preserved EFLAGS -> push 0x6FAF4249 fall-through / push 0x6FAF43BE early-out; ret). E9-detour the EPILOGUE @0x6FAF43BE (5 bytes 83C420 C3 CC = add esp,0x20;ret) -> exit stub (pushfd/pushad; depth-- underflow-guarded; if depth==0 restore scr; popad/popfd; add esp,0x20; ret). Hooking the GATE (not body 0x6FAF4249) puts scr=0 BEFORE the prologue tile-collection reads it; every invocation incl. early-out balances depth. Only scr in {1,2} virtualized (0 and special-3 left alone). Blob is PIC for savedScr(+0x78)/depth(+0x7C) via CALL/POP; 5 absolute D2Client refs relocated to live cb (ASLR-safe). Uses eso_codecave_alloc(0x80) + eso_detour (verify-then-write, auto-refuses double-hook vs PanelWorld2P:reseed-ret which shares 0x6FAF43BE). VERIFICATION: my capstone disasm + byte-compare vs live binary PASSED (gate/epi bytes match, JNE target 0x6FAF43BE, 5 reloc fields correct, push targets correct). Then a 3-agent adversarial workflow ALL returned CONFIRMED_SAFE: (1) blob stack-balanced/EFLAGS-correct/depth-safe/PIC-correct; (2) DrawGame single-entry/single-exit, nothing branches into either E9, ALL exits funnel through 0x6FAF43BE, nothing enters 0x6FAF4249; (3) epilogue-restore scope safe -- scr is a D2Client-PRIVATE global, the 6 post-PASS2 tail calls are world/scene finalization + cross-DLL thunks (D2Win/D2gfx can't read scr), no UI/panel/hit-test runs inside DrawGame's tail. Only caveat (informational): a callee longjmp/throw would strand the guard, but D2's draw path uses neither. BUILT 1.17.0-scrguard (Zig cc x86, LoadLibrary OK), DEPLOYED C:\\Diablo II\\esoteric.dll (266240 bytes, sha 67728A57). INI clean-test config: PanelWorldScrGuard=1, FloorPanelShiftFix=0 (consumer patches reverted -> should compute 0 under the guard), PanelWorldNoShift=0, SecondPass=1 (A-E off), D2DXWiden=1. AWAITING Doug's live test: does the floor un-shift full-width behind the panel? does the panel still render + clicks stay coherent? log line to confirm install: '[feat] ScrGuard: transactional scr=0 world-pass guard ARMED'.", "refs": ["finding.floor_fix_CONVERGENT_scr_virtualize", "finding.floor_collection_shift_cullblock", "finding.floor_patch_v115_CONFIRMED_shear_gone"]} {"id": "finding.scrguard_LIVE_black_resolved_offx_recenter_remains", "kind": "finding", "date": "2026-07-20", "title": "v1.17 scr-guard LIVE TEST: BLACK DEAD-ZONE RESOLVED -- world now renders FULL-WIDTH BEHIND both panels (the ultimate goal's hard part). Remaining = DispW/4 camera RECENTER (offX), a separate lever.", "body": "Doug's live test of the transactional scr=0 world-pass guard (v1.17): the black dead-zone is GONE -- the world renders full-width behind BOTH the inventory (right) and character (left) panels (grass/walls/NPCs continue behind the panel art). This is the 'world behind panels' goal's hardest part, achieved. Mechanism confirmed: guard holds scr=0 across DrawGame -> the native no-panel draw-window computes full width -> nothing scissored to black. NOTE this also proved the widen worker (eso_pw_widen @0x6FAF4302) is NEUTERED by the guard (it early-returns on mode!=1&&!=2, and the guard makes mode=0 inside the pass) -- so the full-width comes from the GUARD's scr=0 (native no-panel draw window), not the widen worker. REMAINING BUG: the world still SHIFTS when a panel opens (right panel -> world slides LEFT; left panel -> world slides RIGHT) = the vanilla DispW/4 play-area RECENTER. This is a SEPARATE lever from the scr-gated width: it rides in offX = GeneralPlayAreaCameraShiftX @0x6FBCC418, a STORED camera offset the panel handler writes ONCE at panel-open, OUTSIDE the world pass -- so the guard's scr=0 never resets it. offX is written-once and is NOT a detection flag (unlike scr), so pinning it 0 is safe + keeps hit-test coherent (screen<->world both use offX=0). NEXT: re-armed the async offX-hold (ini PanelWorldNoShift=1, pw_hold_offx_noshift) to test whether offX is the sole remaining lever. If the world centers -> fold offX into the guard transactionally (entry: save+zero offX@0x6FBCC418 alongside scr; exit: restore) for a clean race-free fix. If still shifted -> the recenter is in scrollX (scroll origin) and hold that instead.", "refs": ["impl.scrguard_v117_built_verified_deployed", "finding.floor_fix_CONVERGENT_scr_virtualize"]} {"id": "finding.wall_shift_SOLVED_drawwinL_ctx04", "kind": "finding", "date": "2026-07-20", "title": "WALL/ROOF SHIFT SOLVED: carrier = render-ctx drawWinL(ctx+0x04), baked -/+DispW/4 at panel-toggle by setter 0x6FB3A4D0; pin ctx+0x04=0/ctx+0x0C=DispW -> world whole behind panels. Live-confirmed.", "body": "The last lever. After scr-guard (scr=0 world pass) + offX-hold locked floor/units/objects, WALLS+ROOFS still slid +/-320. A 4-agent workflow (find-wall-lever) traced it: the panel-toggle handlers (0x6FAEB0A0 inventory/skill; the 0x6FB2F0C3/3A9/648 family) compute DispW/4 and do TWO things: (1) write offX(0x6FBCC418)+scr(0x6FBCC414) [already neutralized], AND (2) fold +/-DispW/4 into a viewport CENTER (ecx=[0x6FBA9E14]+/-DispW/4) passed to the generic draw-window setter 0x6FB3A4D0, which BAKES it into the render-context RECT: drawWinL @ ctx+0x04 and drawWinR @ ctx+0x0C (ctx=*[0x6FBCC3C4]). This bake happens at TOGGLE time (not per-frame; 0x6FB3A4D0 has ~110 callers, none per-frame), so no per-frame guard reaches it. FLOOR is immune because DrawGame re-derives scrollX(ctx+0x24) FROM drawWinL each frame -> drawWinL cancels in screenX=drawWinL-scrollX+tileAbsX; UNITS ride offX (held 0). But the wall/roof drawers (0x6FB3AE00/6C0/140) project through the baked drawWinL RAW with no cancelling term -> the +/-320 survives. nViewXOffset(0x6FB9A9CC) is DEAD CODE (0 refs whole-file) -- confirmed why holding it did nothing. VERIFICATION (couldn't be proven on-disk: wall accessors are D2gfx ordinal imports): LIVE same-user RPM read confirmed drawWinL(ctx+0x04): 0 panel-CLOSED -> -320 with RIGHT panel open (drawWinR 1280->960). LIVE WPM poke: forcing drawWinL=0/drawWinR=DispW while the inventory was open SNAPPED the walls into alignment with the floor (Doug confirmed y). FIX v1.18: pw_hold_offx_noshift (the offX-hold thread) now also pins ctx+0x04=0 and ctx+0x0C=DispW when a panel is open (ini PanelWorldHoldDrawWin=1). Race-free: drawWinL is written once at toggle, DrawGame only READS it. This completes 'world whole behind panels': scr-guard (width/black) + offX-hold (units) + drawWin-hold (walls/roofs/floor coherence). Live-read toolkit: scratchpad live_ctx_read.py / live_drawwin_poke.py.", "refs": ["finding.scrguard_LIVE_black_resolved_offx_recenter_remains", "impl.scrguard_v117_built_verified_deployed", "finding.floor_fix_CONVERGENT_scr_virtualize"]} {"id": "milestone.world_behind_panels_DONE_v118", "kind": "milestone", "date": "2026-07-20", "title": "DONE (v1.18 CONFIRMED LIVE): the world renders WHOLE behind the side panels -- black gone, floor+units+objects+walls+roofs all static, full-width, coherent. The hard part is over.", "body": "Doug confirmed the v1.18 relaunch: with the inventory/character panels open, the ENTIRE world (ground tiles, NPCs, objects, AND walls/roofs) holds static and full-width behind the opaque panels -- no black dead-zone, no shift, no shear, world coherent, panel drawn on top. This is the goal the esoteric.dll PanelWorld feature was built for. Shipped as C:\\Diablo II\\esoteric.dll 1.18.0-worldwhole. Achieved by three composed levers (see [[solution.world_behind_panels_ARCHITECTURE]]). Remaining: Doug's cleanup list (config tidy, retire the dead shift-hacks + the ineffective wall/roof patches) -- polish, not the hard part.", "refs": ["solution.world_behind_panels_ARCHITECTURE", "finding.wall_shift_SOLVED_drawwinL_ctx04"]} {"id": "solution.world_behind_panels_ARCHITECTURE", "kind": "solution", "date": "2026-07-20", "title": "CRYSTALLIZED SOLUTION -- world-behind-panels = THREE INDEPENDENT levers (there is NO single shift global). scr-guard (black/width) + offX-hold (units) + drawWin-hold (walls/roofs). All in esoteric.dll PanelWorld.", "body": "GOAL: at 1280x720, render the D2 LoD 1.13c world FULL-WIDTH and UN-SHIFTED behind the opaque side panels (inventory=right/scr1, character=left/scr2), instead of vanilla's DispW/4 (=320) play-area recenter that hides the world and leaves a black dead-zone.\n\nKEY INSIGHT (why it took so long): the panel shift is injected in THREE STRUCTURALLY INDEPENDENT places, each read by a different render layer -- there is no one global to zero. Every single-lever attempt fixed one layer and exposed the next.\n\nTHE THREE LEVERS (all live, all in PanelWorld, esoteric.dll):\n 1. scr-GUARD (kills BLACK / width). Transactional virtualization of scr=ScreenOpenMode(0x6FBCC414)=0 for the ENTIRE DrawGame world pass: E9-detour the gate @0x6FAF4243 (save scr, zero for scr in {1,2}, depth-count, reproduce the JNE) + the epilogue @0x6FAF43BE (restore). Makes the scr-gated draw-window + tile-cull compute the full no-panel width -> nothing scissored to black. ini PanelWorldScrGuard=1. Verified CONFIRMED_SAFE (blob byte-correct, single-entry/single-exit, epilogue-restore scope). Makes the old consumer patches (0x6FB1027D je->jmp, 0x6FB10D12 sub->nop) REDUNDANT.\n 2. offX-HOLD (kills UNIT/NPC/OBJECT recenter). Async thread pins offX=GeneralPlayAreaCameraShiftX(0x6FBCC418)=0 while a panel is open. offX is written once at panel-open and read only by the 5 unit/object/overhead-text projections; holding 0 un-recenters them. Race-free (written-once). ini PanelWorldNoShift=1 (arms pw_hold_offx_noshift).\n 3. drawWin-HOLD (kills WALL/ROOF shift). Same thread also pins the render-context draw-window drawWinL(ctx+0x04)=0 and drawWinR(ctx+0x0C)=DispW (ctx=*[0x6FBCC3C4]). The panel-toggle setter 0x6FB3A4D0 bakes +/-DispW/4 into that RECT at open time; walls/roofs (PASS2 drawers 0x6FB3AE00/6C0/140) project through it RAW. The floor is immune (DrawGame re-derives scrollX FROM drawWinL each frame so it cancels) and units ride offX -- only walls needed this. Race-free (drawWinL written once at toggle, DrawGame only reads). ini PanelWorldHoldDrawWin=1. LIVE-CONFIRMED: drawWinL 0(closed)->-320(right panel); WPM poke to 0 snapped the walls into alignment.\n\nSupporting: SGD2FreeRes sets DispW=1280 live; D2DXWiden forces D2DX gameSize=1280 so x>=960 isn't scissored (ini D2DXWiden=1). nViewXOffset(0x6FB9A9CC) is DEAD CODE in 1.13c (0 refs) -- ignore it.\n\nWINNING ini [Features]: PanelWorldScrGuard=1, PanelWorldNoShift=1, PanelWorldHoldDrawWin=1, D2DXWiden=1, PanelWorld=1, PanelWorldSecondPass=1 (forces the old A-E shift-hacks off), FloorPanelShiftFix=0 (redundant under the guard). PanelWorldWallFix (the 3 wall/roof view-setup patches) applied but did NOTHING -- retire it.\n\nMETHOD that cracked it: read the actual live binary (not assume vanilla), static disasm (capstone) + ChatGPT frontier analysis + a 4-agent workflow to fan out the wall trace, then LIVE same-user RPM/WPM to confirm each lever before baking (esoteric-dll\tools + scratchpad live_ctx_read.py / live_drawwin_poke.py).", "refs": ["finding.wall_shift_SOLVED_drawwinL_ctx04", "impl.scrguard_v117_built_verified_deployed", "finding.scrguard_LIVE_black_resolved_offx_recenter_remains", "finding.floor_fix_CONVERGENT_scr_virtualize"]} {"id": "finding.both_panels_scr3_black_FIXED", "kind": "finding", "date": "2026-07-20", "title": "BOTH-PANELS (scr=3) all-black FIXED (v1.18.1): D2 SKIPS the world passes when ScreenOpenMode=3 (cmp[scr],3;je); scr-guard now virtualizes ANY non-zero scr {1,2,3}.", "body": "With BOTH side panels open (inventory right + character left), ScreenOpenMode(scr @0x6FBCC414)=3 and the whole world went BLACK. LIVE read (both panels open): scr=3, offX=0, drawWinL(ctx+0x04)=0, drawWinR(ctx+0x0C)=1280 -- i.e. the both-panels draw window is ALREADY full+unshifted, so this was NOT a shift; D2 simply SKIPS the world render passes when scr==3 (the DrawGame `cmp [scr],3; je ` gates before the passes). The scr-guard originally virtualized only scr in {1,2} (ChatGPT deliberately left 3 alone), so scr=3 fell through -> passes skipped -> black. FIX: changed the guard's entry-stub condition from `cmp eax,1;je / cmp eax,2;jne` to `test eax,eax; je` (same 10 bytes, no relocation drift) so it virtualizes scr=0 for ANY non-zero scr {1,2,3}; with scr=0 the cmp/je no longer skips -> passes run -> world renders behind both panels. offX/drawWin hold thread condition also widened `mode==1||2` -> `mode!=0` (idempotent for scr=3 since its window is already correct). Shipped v1.18.1-bothpanels, Doug confirmed fixed. Verified the modified blob via capstone before deploy.", "refs": ["solution.world_behind_panels_ARCHITECTURE", "milestone.world_behind_panels_DONE_v118", "finding.wall_shift_SOLVED_drawwinL_ctx04"]} {"id": "codex.MULTIRES_SetResolution", "kind": "function", "module": "D2Client.dll", "rva": "0x10df0", "date": "2026-07-20", "title": "MULTIRES_SetResolution", "body": "1.13c render/viewport function name HARVESTED from the Codex D2MOO KB (B2 wave-1, evidence class verified_cfg_translation; subsystem world_viewport). VA 0x6FAC0DF0. Provenance: E:\\Codex-D2MOO-1.13c-KB\\mappings\b2-wave1-results.csv (read-only). Codex names are cross-version CFG/ABI translations against STOCK 1.13c; verify vs the live patched image before relying on bytes.", "refs": ["finding.codex_render_name_harvest_2026_07_20"]} {"id": "codex.SetResolutionFromOptions", "kind": "function", "module": "D2Client.dll", "rva": "0x65180", "date": "2026-07-20", "title": "SetResolutionFromOptions", "body": "1.13c render/viewport function name HARVESTED from the Codex D2MOO KB (B2 wave-1, evidence class verified_cfg_translation; subsystem world_viewport). VA 0x6FB15180. Provenance: E:\\Codex-D2MOO-1.13c-KB\\mappings\b2-wave1-results.csv (read-only). Codex names are cross-version CFG/ABI translations against STOCK 1.13c; verify vs the live patched image before relying on bytes.", "refs": ["finding.codex_render_name_harvest_2026_07_20"]} {"id": "codex.GetResolutionRegistry", "kind": "function", "module": "D2Client.dll", "rva": "0x66270", "date": "2026-07-20", "title": "GetResolutionRegistry", "body": "1.13c render/viewport function name HARVESTED from the Codex D2MOO KB (B2 wave-1, evidence class verified_cfg_translation; subsystem world_viewport). VA 0x6FB16270. Provenance: E:\\Codex-D2MOO-1.13c-KB\\mappings\b2-wave1-results.csv (read-only). Codex names are cross-version CFG/ABI translations against STOCK 1.13c; verify vs the live patched image before relying on bytes.", "refs": ["finding.codex_render_name_harvest_2026_07_20"]} {"id": "codex.SetResolutionRegistry", "kind": "function", "module": "D2Client.dll", "rva": "0x662a0", "date": "2026-07-20", "title": "SetResolutionRegistry", "body": "1.13c render/viewport function name HARVESTED from the Codex D2MOO KB (B2 wave-1, evidence class verified_cfg_translation; subsystem world_viewport). VA 0x6FB162A0. Provenance: E:\\Codex-D2MOO-1.13c-KB\\mappings\b2-wave1-results.csv (read-only). Codex names are cross-version CFG/ABI translations against STOCK 1.13c; verify vs the live patched image before relying on bytes.", "refs": ["finding.codex_render_name_harvest_2026_07_20"]} {"id": "codex.DisableScrollOfInifussRect", "kind": "function", "module": "D2Client.dll", "rva": "0x7c380", "date": "2026-07-20", "title": "DisableScrollOfInifussRect", "body": "1.13c render/viewport function name HARVESTED from the Codex D2MOO KB (B2 wave-1, evidence class verified_cfg_translation; subsystem world_render). VA 0x6FB2C380. Provenance: E:\\Codex-D2MOO-1.13c-KB\\mappings\b2-wave1-results.csv (read-only). Codex names are cross-version CFG/ABI translations against STOCK 1.13c; verify vs the live patched image before relying on bytes.", "refs": ["finding.codex_render_name_harvest_2026_07_20"]} {"id": "codex.DrawSummitBackground", "kind": "function", "module": "D2Client.dll", "rva": "0x8a6c0", "date": "2026-07-20", "title": "DrawSummitBackground", "body": "1.13c render/viewport function name HARVESTED from the Codex D2MOO KB (B2 wave-1, evidence class verified_cfg_translation; subsystem world_render). VA 0x6FB3A6C0. Provenance: E:\\Codex-D2MOO-1.13c-KB\\mappings\b2-wave1-results.csv (read-only). Codex names are cross-version CFG/ABI translations against STOCK 1.13c; verify vs the live patched image before relying on bytes.", "refs": ["finding.codex_render_name_harvest_2026_07_20"]} {"id": "codex.SetTileCullingBound", "kind": "function", "module": "D2Client.dll", "rva": "0x8a4d0", "date": "2026-07-20", "title": "SetTileCullingBound", "body": "1.13c render/viewport function name HARVESTED from the Codex D2MOO KB (B2 wave-1, evidence class verified_cfg_translation; subsystem world_viewport). VA 0x6FB3A4D0. Provenance: E:\\Codex-D2MOO-1.13c-KB\\mappings\b2-wave1-results.csv (read-only). Codex names are cross-version CFG/ABI translations against STOCK 1.13c; verify vs the live patched image before relying on bytes.", "refs": ["finding.codex_render_name_harvest_2026_07_20"]} {"id": "codex.MULTIRES_DrawGroundTiles", "kind": "function", "module": "D2Client.dll", "rva": "0x143d0", "date": "2026-07-20", "title": "MULTIRES_DrawGroundTiles", "body": "1.13c render/viewport function name HARVESTED from the Codex D2MOO KB (B2 wave-1, evidence class verified_cfg_translation; subsystem world_render). VA 0x6FAC43D0. Provenance: E:\\Codex-D2MOO-1.13c-KB\\mappings\b2-wave1-results.csv (read-only). Codex names are cross-version CFG/ABI translations against STOCK 1.13c; verify vs the live patched image before relying on bytes.", "refs": ["finding.codex_render_name_harvest_2026_07_20"]} {"id": "codex.MULTIRES_GroundTileParamSetup", "kind": "function", "module": "D2Client.dll", "rva": "0x14050", "date": "2026-07-20", "title": "MULTIRES_GroundTileParamSetup", "body": "1.13c render/viewport function name HARVESTED from the Codex D2MOO KB (B2 wave-1, evidence class verified_cfg_translation; subsystem world_render). VA 0x6FAC4050. Provenance: E:\\Codex-D2MOO-1.13c-KB\\mappings\b2-wave1-results.csv (read-only). Codex names are cross-version CFG/ABI translations against STOCK 1.13c; verify vs the live patched image before relying on bytes.", "refs": ["finding.codex_render_name_harvest_2026_07_20"]} {"id": "codex.MULTIRES_DrawRoofTiles", "kind": "function", "module": "D2Client.dll", "rva": "0x13a00", "date": "2026-07-20", "title": "MULTIRES_DrawRoofTiles", "body": "1.13c render/viewport function name HARVESTED from the Codex D2MOO KB (B2 wave-1, evidence class verified_cfg_translation; subsystem world_render). VA 0x6FAC3A00. Provenance: E:\\Codex-D2MOO-1.13c-KB\\mappings\b2-wave1-results.csv (read-only). Codex names are cross-version CFG/ABI translations against STOCK 1.13c; verify vs the live patched image before relying on bytes.", "refs": ["finding.codex_render_name_harvest_2026_07_20"]} {"id": "codex.MULTIRES_DrawLowerWallTiles", "kind": "function", "module": "D2Client.dll", "rva": "0x9ec10", "date": "2026-07-20", "title": "MULTIRES_DrawLowerWallTiles", "body": "1.13c render/viewport function name HARVESTED from the Codex D2MOO KB (B2 wave-1, evidence class verified_cfg_translation; subsystem world_render). VA 0x6FB4EC10. Provenance: E:\\Codex-D2MOO-1.13c-KB\\mappings\b2-wave1-results.csv (read-only). Codex names are cross-version CFG/ABI translations against STOCK 1.13c; verify vs the live patched image before relying on bytes.", "refs": ["finding.codex_render_name_harvest_2026_07_20"]} {"id": "codex.D2SetScrollEndFunc", "kind": "function", "module": "D2Client.dll", "rva": "0x7ae80", "date": "2026-07-20", "title": "D2SetScrollEndFunc", "body": "1.13c render/viewport function name HARVESTED from the Codex D2MOO KB (B2 wave-1, evidence class verified_cfg_translation; subsystem world_viewport). VA 0x6FB2AE80. Provenance: E:\\Codex-D2MOO-1.13c-KB\\mappings\b2-wave1-results.csv (read-only). Codex names are cross-version CFG/ABI translations against STOCK 1.13c; verify vs the live patched image before relying on bytes.", "refs": ["finding.codex_render_name_harvest_2026_07_20"]} {"id": "codex.TileRoofDraw", "kind": "function", "module": "D2Client.dll", "rva": "0x79d30", "date": "2026-07-20", "title": "TileRoofDraw", "body": "1.13c tile-draw routine name HARVESTED from Codex KB (B2 wave-1, dispositioned_verified_split_lineage = verified identity but the 1.10f lineage split/merged, so not a clean 1:1 translation). VA 0x6FB29D30.", "refs": ["finding.codex_render_name_harvest_2026_07_20"]} {"id": "codex.TileShadowOrSpecialDraw", "kind": "function", "module": "D2Client.dll", "rva": "0x79c80", "date": "2026-07-20", "title": "TileShadowOrSpecialDraw", "body": "1.13c tile-draw routine name HARVESTED from Codex KB (B2 wave-1, dispositioned_verified_split_lineage = verified identity but the 1.10f lineage split/merged, so not a clean 1:1 translation). VA 0x6FB29C80.", "refs": ["finding.codex_render_name_harvest_2026_07_20"]} {"id": "codex.TileSpecialOrientationDraw", "kind": "function", "module": "D2Client.dll", "rva": "0x79e20", "date": "2026-07-20", "title": "TileSpecialOrientationDraw", "body": "1.13c tile-draw routine name HARVESTED from Codex KB (B2 wave-1, dispositioned_verified_split_lineage = verified identity but the 1.10f lineage split/merged, so not a clean 1:1 translation). VA 0x6FB29E20.", "refs": ["finding.codex_render_name_harvest_2026_07_20"]} {"id": "codex.UpperPassHelper_7A180", "kind": "function", "module": "D2Client.dll", "rva": "0x7a180", "date": "2026-07-20", "title": "UpperPassHelper_7A180", "body": "1.13c tile-draw routine name HARVESTED from Codex KB (B2 wave-1, dispositioned_verified_split_lineage = verified identity but the 1.10f lineage split/merged, so not a clean 1:1 translation). VA 0x6FB2A180.", "refs": ["finding.codex_render_name_harvest_2026_07_20"]} {"id": "codex.UpperPassHelper_7A260", "kind": "function", "module": "D2Client.dll", "rva": "0x7a260", "date": "2026-07-20", "title": "UpperPassHelper_7A260", "body": "1.13c tile-draw routine name HARVESTED from Codex KB (B2 wave-1, dispositioned_verified_split_lineage = verified identity but the 1.10f lineage split/merged, so not a clean 1:1 translation). VA 0x6FB2A260.", "refs": ["finding.codex_render_name_harvest_2026_07_20"]} {"id": "codex.UpperPassHelper_7A500", "kind": "function", "module": "D2Client.dll", "rva": "0x7a500", "date": "2026-07-20", "title": "UpperPassHelper_7A500", "body": "1.13c tile-draw routine name HARVESTED from Codex KB (B2 wave-1, dispositioned_verified_split_lineage = verified identity but the 1.10f lineage split/merged, so not a clean 1:1 translation). VA 0x6FB2A500.", "refs": ["finding.codex_render_name_harvest_2026_07_20"]} {"id": "finding.codex_render_name_harvest_2026_07_20", "kind": "finding", "date": "2026-07-20", "title": "HARVEST from Codex D2MOO KB: 18 verified 1.13c render/viewport function NAMES land on addresses we had only numerically -- incl. SetTileCullingBound = 0x6FB3A4D0 (the wall-shift viewport-origin setter) and the 0x6FB29C80/D30/E20 tile sub-draws", "body": "One-way harvest (Codex repo is READ-ONLY to us, see [[codex-d2moo-kb-readonly]]) of Codex's B2 wave-1: 32 D2Client render/viewport rows -> 12 verified_cfg_translation + 6 verified-but-split-lineage. CROSS-VALIDATION with our own independent RE: (1) **0x6FB3A4D0 = SetTileCullingBound** -- the generic play-area viewport-origin setter our wall-shift workflow proved BAKES +/-DispW/4 into drawWinL(ctx+0x04) at panel-toggle; Codex reached it independently and gives it a name. (2) **0x6FB29C80 / 0x6FB29D30 / 0x6FB29E20 = TileShadowOrSpecialDraw / TileRoofDraw / TileSpecialOrientationDraw** -- exactly the tile-pass sub-draws in our render-pipeline notes, previously unnamed. (3) **0x6FAC0DF0 = MULTIRES_SetResolution** -- our 'FOV setup fn'. (4) 0x6FB3A6C0 = DrawSummitBackground -- NOTE this corrects an earlier working assumption that 0x6FB3A6C0 was a wall/roof projection routine. **OPEN DISCREPANCY: 0x6FB4EC10** -- our render-pipeline notes call it the PASS2 'unit draw'; Codex names it MULTIRES_DrawLowerWallTiles. Both may be partly right (shared/adjacent routine) but this must be resolved against the binary before either name is asserted. CAVEAT: Codex verifies against STOCK 1.13c (VersionChanger set, D2Client base 0x6FAB0000 -- same as ours); live patched bytes differ. Also harvested: Codex's CE-library cross-join DEMOTED two false same-ordinal D2MOO mappings (D2Common+0x31940 = STATS_GetBeltGoldLimit not DUNGEON_CallRoomCallback; D2Common+0x37D50 = STATLISTS_GetSkillId not STATES_CheckStateMaskShatterOnUnit).", "refs": ["solution.world_behind_panels_ARCHITECTURE", "finding.wall_shift_SOLVED_drawwinL_ctx04"]} {"id": "finding.export_ordinal_mapping_is_unreliable_2026_07_21", "kind": "finding", "date": "2026-07-21", "title": "MEASURED: same-number PE export ordinal is NOT a valid 1.10f->1.13c semantic mapping method -- 54/56 audited rows FAILED (96.43% raw, 98.54% population-weighted); D2Common failed 16/16", "body": "Result of the OA1 stratified audit in the Codex D2MOO KB (READ-ONLY to us, see [[codex-d2moo-kb-readonly]]). Codex had built ~91% of its 1.10f->1.13c 'verified' coverage on the class verified_export_ordinal = 'the same export ordinal exists in both stock versions and lands in a valid section'. A 56-row stratified sample (D2Common 16, D2Game 16, D2Gfx 5, D2Win 14, D2Net 3, D2Lang 2) applied a real exit gate (entry boundary, CFG, semantic constants, ABI, caller/callee neighborhood). **54 of 56 FAILED.** Only D2Game::GAME_CloseAllGames and D2Lang::Unicode::strnicmp survived. D2Common failed 16/16. ROOT CAUSE: the PE export table was reordered between 1.10f and 1.13c, so equal ordinal number != same function; the method was pairing unrelated routines. This measures ordinal-equality-as-semantics, NOT the validity of either version's export table. CONSEQUENCE: Codex's headline coverage fell 1,536 -> 1,482 rows on the sample alone, and the ~1,325 unaudited ordinal-only rows cannot be credited -- applying the measured rate leaves roughly 155-200 genuinely evidence-backed rows (~3% of the 5,749-row parity queue), not ~26%. PRIOR SIGNAL: the harvest of Doug's own CE library had already caught two false same-ordinal mappings (D2Common+0x31940 = STATS_GetBeltGoldLimit not DUNGEON_CallRoomCallback; D2Common+0x37D50 = STATLISTS_GetSkillId not STATES_CheckStateMaskShatterOnUnit) -- those were not anomalies, they were the tip of a ~97% failure rate. **RULE FOR THIS GRIMOIRE: never import a cross-version mapping whose only evidence is a matching export ordinal.** Our harvest of Codex render/viewport names (see [[finding.codex_render_name_harvest_2026_07_20]]) deliberately took only verified_cfg_translation and split-lineage rows, so no ordinal-class mapping ever entered this grimoire. Corollary worth keeping: Doug's hand-verified CE/live RE outperformed ~1,300 machine-inferred rows.", "refs": ["finding.codex_render_name_harvest_2026_07_20"]}