Skip to content

Releases: VTSTech/D2LoD-libslang-vk

D2LoD Vanilla+0.0.7-R98

Pre-release

Choose a tag to compare

@VTSTech VTSTech released this 03 Nov 10:13
image image image

Release notes — R88 → R98

R88 — Vanilla+ 0.0.7-R88 — 2026-11-02 — tag R88 @ 9526633c (merge 1d401785)

The second upstream sync of the 0.0.7 line — and the SUPERSESSION LEDGER OPENS.

Upstream c8445e73..bc47c6bc (9 commits) merged with the Vanilla+ surface intact:
Ghidra DB 1839 → 1851, byte match 6,232 → 6,242 of 14,642 functions (19.50% →
19.54% of bytes), 22 conflicts / 27 hunks resolved. Where upstream recovered the
retail form of a fork fix, upstream wins and the fork keeps the root-cause note:

  • fix 16 (Defect 13: SFX silent, music OK) superseded by upstream's
    D2FloatIntUnion — same root cause, retail-faithful form.
  • The R54/R85 quest-gossip hand-tables (#13,
    #22) superseded by
    upstream's verbatim retail tables — all 39 aNpcGossipData externs now sized
    retail-exact (28 were unsized); the track-J singular-table watch resolves.
  • Sound constants take upstream's exact decoded decimals (the -2000.0 centibel
    diagnosis preserved).
  • Checked and NOT superseded: the issue #11
    [glide fix 11] hook (the wrapper ships from the Glide3xVK branch, which
    upstream does not carry).

Gates 326/326 (10 stale expectations re-pinned to the superseding state).
Field-run green 2026-11-03 riding the R91 pass.

R89 — Vanilla+ 0.0.7-R89 — 2026-11-02 — tag R89 @ 4014ef65

The monster-components data-model fix (issue #8 hardening).

Raised skeleton/monster component bytes were overlaying pUnitDataPlayer->szCharName[4..];
they now write the monster unit-data union (pUnitDataMonster->Components[0x10],
->pAiGeneral) with null guards (SKILLNEC_SetSkeletonComponentsByMasteryLvl,
D2Game/UNIT/Monster.cpp). Skeleton classes 0x16b/0x16c get their palshift.dat
ownership polarity forced from the live hostility check regardless of byUtrans
(D2Client/UNIT/CUnit.cpp). Field-verified 2026-11-03 riding the R90b run —
"Skeletons are finally white again" (issue #8).

R90 / R90b — Vanilla+ 0.0.7-R90(b) — 2026-11-03 — tags R90 @ fff470d7 + R90b @ 3726f3ce (merge 77e87e02)

The third upstream sync + two Windows-build blockers fixed.

Upstream bc47c6bc..57380e21 (2 commits) merged: Ghidra DB 1851 → 1855, byte match
6,273 of 14,642 functions (19.51% of bytes), 3 conflicts / 9 hunks. The ledger grows:
upstream rebuilt the D3D ground-tile index buffers in retail form (stack
aStripIndices[60] prefill → properly-extent gpD3DGroundTileVertexBuffer; fan
gdwRendererMode = {0,5,0x23,0x1e} byte-match verified), superseding fork fixes 24
(fullscreen black ground) and 25 (perspective floor diagonal bars) — DrawGroundTile
and InitGroundTileCache are now byte-identical to upstream. D2UnitFindDataStrc.h
deleted upstream (structs relocated to D2Common/Unit.h).

R90b fixes the owner's first MSYS2 build of R90: a stale D2UnitFindDataStrc.h
include in VanillaPlusCore.cpp (kitchen-sink block missed by the merge) and a
RENDERER_D3D_DrawGlyph splice referencing float globals the upstream regen deleted.
Cross-verified in the sandbox with llvm-mingw (whole-tree include audit: 14,915
quoted includes → 0 unresolvable; d2.exe links pei-i386). Field-run green
2026-11-03
(see R91).

R91 — Vanilla+ 0.0.7-R91 — 2026-11-03 — commit fd46e40a (tag pending)

The field-verify round — one report, two closures.

The owner's MSYS2 MINGW32 build of R90b went green and the game runs:
"Skeletons are finally white again" — issue #8
RESOLVED IN THE FIELD (the R50 roster-recolor polarity + R51 spawn-polarity write +
R89 component hardening all confirmed on one build; GitHub close pending the owner).
R90/R90b field verification closed with it. Docs-only otherwise; regular rounds
return to the overlay-zip workflow (git bundles reserved for upstream-merge rounds).
Gates 326/326.

R92 — Vanilla+ 0.0.7-R92 — 2026-11-03 — commit fc84bd67 (tag pending)

Issue #26 fix round 1 — the 720p panel blackness root-caught.

"[720p] With only Left or Right UI Panel open, Black triangles on that side of
screen" — root cause: every panel-open adjustment in the world pipeline is a
fraction of the window width, tuned for 640x480/800x600 where the open 800-class
panel reaches the screen edge. The Vanilla+ wide modes center that rigid 800 px UI
(240 px margins at 1280x720), so the culls still assumed edge-hugging geometry and
the strip beyond the open panel was culled to the black backbuffer. Fixed for wide
layouts only (retail byte-identical): the tile walk keeps the full panned span
(Path.cpp), the perspective cull rects open the margin side (D3D + Glide), unit
clicks reject only the real panel rectangle (CUnit.cpp — margin units clickable
again), town-portal fade and weather clamps span the full width. Gates 332/332.
Field result: PARTIAL — left side fixed; right side and both-panels still black.

R93 — Vanilla+ 0.0.7-R93 — 2026-11-03 — commit ab34c7ea (tag pending)

Issue #26 fix round 2 — the three remaining family members.

The border-3 ViewDraw2 world-draw skip (Game.cpp): with both panels open the
whole world pass never ran — every renderer, both perspective modes. The
bottom-band vertical cuts: non-perspective builders anchor-cut at h-0xf,
rendering the perspective-OFF bottom strip black. Plus the case-2 pan-anchor flip.
4 files; gates +6. Field result: PARTIAL — non-perspective single panels
verified; both panels still black; the perspective right margin survived.

R94 — Vanilla+ 0.0.7-R94 — 2026-11-03 — commit a6ef88b9 (tag pending)

Issue #26 fix round 3 — both panels closed.

Fixed the both-panels artifacts (the border-3 world-draw delivery + the D3D/Glide
bottom-band anchors): "both panels open, no more blackness" — green in BOTH
perspective modes and BOTH renderers. Field result: MOSTLY GREEN — the
perspective-ON right-panel margin and the world-slide question moved to R95.

R95 — Vanilla+ 0.0.7-R95 — 2026-11-03 — commit d1e7e350 (tag pending)

Issue #26 round 4 + the no_panel_shift feature — "Can we open the panel without
moving anything?"

Answer: the quarter-screen world slide with one panel open is VANILLA
(TypeOfUiOverlayOverWorld pans the world by ∓ScreenSizeX/4 to re-center the
action in the uncovered strip; exact only when the open panel reaches the screen
edge — 640x480/800x600). At 720p the floating 800-class UI makes the slide drag the
world out from under the visible margins. R95 adds the opt-in no_panel_shift
d2vp.ini feature: while 1, a single open panel takes the border-0 world pipeline
verbatim (Path.cpp camera gate + a neutralizer at the 11 world-draw origins) — the
renderers receive 0 and take their own full-screen no-pan path; zero renderer edits;
retail dims byte-identical; 9 files; gates +10. Field-verified in Glide: "no
shifting is observed when opening a panel ... All blackness appears fixed in Glide
as well" — issue #26 field-green in Glide.

R96 — Vanilla+ 0.0.7-R96 — 2026-11-03 — commit ce77c056 (tag pending)

Issue #26 round 5 — the D3D perspective-toggle triage (diagnostics only, zero
behavior change).

Owner report: "toggling perspective mode in D3D crashes the game ... Glide can
toggle." R96 ships five one-shot d2boot.log probes bracketing the toggle (videoopt
load/apply, world frame enter/drawn, first D3D perspective DrawGroundTile) plus a
read-out matrix (SMOKE §L item 46). The first field pass named the death: D3D
800x600, ~6.5 s of perspective-ON play, then videoopt: perspective apply ... active=1 -> 0 and halt report: line=200 in the same 15 ms tick — Redivivus "Fog's
unrecoverable-error halt", no access violation.

R97 — Vanilla+ 0.0.7-R97 — 2026-11-03 — commit b4211fbe (tag pending)

Issue #26 round 6 — the promote guards: degrade instead of dying.

line=200 exists at exactly two sites: the retail nIndex > nMaxNodes range halt
inside D3DFLOOR_PromoteNodeToMRU / D3DSUBTILE_PromoteNodeToMRU (the D3D
floor/subtile texture caches). Every static link audited retail-clean, so R97 turns
the death into a logged, self-healing degradation (dead cache → skip the draw;
out-of-range slot word → bootlog mark + heal to the alloc path) and re-arms the
probes as per-flip transition marks (world: perspective now %d, view frame [R97],
d3d: perspective now %d, floor tile pass ... [R97]). Gates 356 → 362. The field
pass returned outcome (b) exactly as designed: the guard fired —
subtile promote out-of-range idx=4097 ... healed to uncached [R97] — the game
continued one step, then AV READ at FF600060. The mark's numbers were the
root-cause data.

R98 — Vanilla+ 0.0.7-R98 — 2026-11-03 — commit 1be20222 (tag pending)

Issue #26 round 7 / #27
— the D3D perspective-toggle death ROOT-CAUSED AND ROOT-FIXED.

Both field numbers decode to one defect: `RENDERER_D3D...

Read more

D2LoD Vanilla+0.0.7-R91

Pre-release

Choose a tag to compare

@VTSTech VTSTech released this 03 Nov 02:59

Closes #8

D2LoD Vanilla+0.0.7-R101

Pre-release

Choose a tag to compare

@VTSTech VTSTech released this 03 Nov 21:25
769bcac
image image image

Release Notes — Vanilla+ working rounds R98 → R101

Four rounds, one storyline: issue #26 (no_panel_shift) goes from
"perspective toggle dies in D3D" to "fixed, field-proven, and toggleable
in-game."
All four rounds carry the 0.0.7 build line — no new ini keys
anywhere, existing d2vp.ini files stay valid as-is.

Round Self-ID Date One-liner
R98 Vanilla+0.0.7-R98 2026-11-03 D3D perspective-toggle death: root cause fixed
R99 Vanilla+0.0.7-R99 2026-11-03 Upstream sync (Ghidra 1864–1877 library rounds)
R100 Vanilla+0.0.7-R100 2026-11-04 Unit-sprite pan regression from the R99 merge — fixed
R101 Vanilla+0.0.7-R101 2026-11-04 no_panel_shift toggle added to the Vanilla+ Options panel

Skip straight to R101 if you are upgrading from anything older — it
contains everything above.


Vanilla+0.0.7-R98 — D3D perspective-toggle death: root cause fixed

Issue #26 round 7. The R97 instrumentation guard fired on its first field
pass, and the log it produced was the smoking gun the probe rows were built
to catch:

d3d: subtile promote out-of-range idx=4097 max=1536 ... healed to uncached [R97]
VEH: fatal exception 0xC0000005 / AV READ at FF600060

What was actually wrong

The D3D flat-wall builder (RENDERER_D3D_BuildWallTileVerticesNoPerspective)
walks its subtile array by byte offset, and the decompiler had typed that
iterator uint8_t — every sibling iterator in the tree is a full-width
int. Accumulating 0x14 per record, it wraps at 256: from the 13th subtile
on, the loop reads the real array shifted +4 bytes. The fake records
explain both artifacts precisely — idx=4097 = 0x1001 is a DT1 wFormat
word mistaken for a cache index (the same word that halted line=200 in R96),
and FF600060 is a wall subtile's {nOffsetY=-160, nOffsetX=+96} pair
mistaken for a pixel pointer. Latent since the original decompilation; it
only ever fired on the first flat-wall frame after a perspective 1 → 0 flip,
which is why D3D sessions that never toggled lived.

Fixed

  • The byte-offset iterator is now int — real records at any subtile count.
    This also kills the silent wrong-record class the wrap could produce
    (wrong-textured quads that never crashed).
  • The R97 promote guards stay verbatim as defense in depth.
  • New confirmation probe: tiles with > 12 subtiles (the exact wrap
    population) log d3d: flat wall subtiles=<n> [R98], first 8 per session.

Verification

SMOKE §L item 48: in D3D, toggle Perspective both directions — no death, no
healed to uncached marks; a few flat wall subtiles= marks are the
expected confirmation data. Then finish the #26 D3D matrix (items 41–45).


Vanilla+0.0.7-R99 — upstream sync (Ghidra 1864–1877 library rounds)

The periodic upstream alignment, done as one merge round: upstream
088c4ee3..94ec239d (one-TU globals made static, 48 functions re-filed into
their source files, msvc8 evidence at 6,478 functions / 20.66% of bytes).
209 files changed, +12,860 / −13,350 — net 490 lines out of the tree.

Highlights relevant to Vanilla+:

  • Retail bodies landed for the unit-sprite draw path (DRAW_WORLD_Unit_1,
    GFX_DrawUnitSelectionShape, …) among the Ghidra 1864–1877 library rounds.
    ⚠️ Known follow-up: these retail bodies re-armed the vanilla ±quarter
    sprite pan in the perspective branch, which the R95 no_panel_shift
    neutralizer didn't cover — fixed in R100 (see below). R99 builds
    should not be used with no_panel_shift=1.
  • Sound-table gates re-pinned to upstream 1870 spellings; the sound-init hwnd
    fix superseded by upstream's 1870 BOOL parameter; texture-cache init
    branches realigned verbatim.
  • The merge was redone cleanly after a first pass broke the ui.cpp build;
    the shipped merge (18838a8b) compiles and all gates are green.

Vanilla+0.0.7-R100 — unit-sprite pan regression fixed (issue #26 round 8)

Field report: "clean build successful. no_panel_shift is still missing. with
it set to 0 shifts normally, when set to 1, player, npc, campfire get pushed
into wrong locations."

Decode

Exactly the three unit classes — players, monsters, objects — riding the
path the R99 merge re-armed. The R95 feature covered every terrain pass
(floor/wall/roof/shadow, weather, automap) with the
PANELSHIFT_BorderForWorld neutralizer, but the pre-1864 unit copies had no
border handling at all (they rode the view rect, already fixed). The new
retail bodies compute sprite screen-x the vanilla way in the perspective
branch: AdjustPerspectivePosition + a hand-applied ±quarter pan keyed on
the real window border
. So with no_panel_shift=1 the world stayed at the
border-0 camera while units — and everything anchored to them — panned one
quarter sideways. no_panel_shift=0 was never affected (there the sprite pan
matches the world pan).

Fixed

All 14 unit-anchored world-render consumers now read the border through
PANELSHIFT_BorderForWorld:

  • Gfx.cpp ×7 — unit sprites, state overlays, shadows, colored/selection
    shapes, DRAW_WORLD_Unit_1
  • GfxUtil.cpp ×1 — unit COF direction
  • Text.cpp ×2 — monster/object hover text
  • ShowItems.cpp ×1 — ground-item label anchor (label culling keeps the
    real border, per charter)
  • ui.cpp ×3 — mercenary HP bar, player name plates, unit/warp tooltip anchor

UI/interaction consumers (panel click rects, hit tests, mouse warps) keep the
real border by charter; no_panel_shift=0 behavior is byte-identical to
before. 5 new gates pin every call-site count — suite 377/377.

Verification

SMOKE items 41a/41b. Owner-confirmed on the field build:
"no_panel_shift is working as intended now."


Vanilla+0.0.7-R101 — the Options-panel toggle (issue #26 round 9)

Field ask: "Great job, no_panel_shift is working as intended now. Let's add
the toggle to the Vanilla+ Options panel."

What's new

Esc → Options → Vanilla+ Options grows a seventh row — No Panel World
Shift
— wired exactly like the existing rows: one entry in the row table
riding the same ini read/write bridge. Nothing else needed touching: the
write bridge already flushes the PANELSHIFT gate cache, so the flip applies
the same frame — the world stays put the moment you flip On, and slides
again the moment you flip Off. No ini edit needed, ever; your existing
[features] no_panel_shift key is read and shown as-is.

Layout

Seven rows overflowed the R67 page geometry (row 7 would have overlapped
Previous Menu by 6 px), so the Previous Menu row moved down one pitch
(0x124 → 0x144): same spacing, still inside the panel box, and
hit-test/hover/draw all move in step via the shared row-geometry helper.

As documented on the ini template since the feature shipped: the feature is
wide-layout only (1280x720 / 1344x700). At 640x480 / 800x600 the row
flips the key but the vanilla slide is kept by design. no_panel_shift=0
behavior unchanged everywhere. Gates 380/380 (3 new).

Verification

SMOKE item 2 now includes the panel round trip: toggle On → open the
character screen at 1280x720 → world stays put (units included); toggle Off →
world slides again.

Full Changelog: R98...R101

D2LoD Vanilla+0.0.7-R88

Pre-release

Choose a tag to compare

@VTSTech VTSTech released this 02 Nov 23:39
image image image

R84 — Vanilla+ 0.0.7-R84 — 2026-11-02 — tag R84 @ 63e020a3

The item-tooltip zero fix (#16).

Items could drop with a mod line reading "0 poison damage over 0 seconds", and
'of Frost' gear could show "+0 Cold Damage": the item-stat tooltip formatter's
single-value elemental/poison branches called the wide-string formatter without the
numeric varargs
(a latent retail-1.14d bug the fork's build layout makes visible), so
any roll whose range collapsed to min==max printed stack residue instead of the value
('of Frost' weapons roll cold-max 1..2 with cold-min fixed at 1 — every drop that
rolled a 1 collapsed; poison collapses through the length rounding). Display-side only —
item stats and generation were never wrong.

  • Field-verified by the owner the same day (SMOKE §J items 37–38 proven at tag).
  • Gates 308 → 311; self-ID Vanilla+0.0.7-R84 (d2boot.log line 1 pins the exe).

R85 — Vanilla+ 0.0.7-R85 — 2026-11-02 — tag R85 @ 71f4772f

The A1Q2 "Sisters' Burial Grounds" turn-in fix (#22).

Blood Raven killed, but Kashya's reward (the rogue mercenary) could not be claimed:
the A1Q2 gossip table was emitted singular (accept line only) while the handler reads
slot 3 whenever RewardAwaits is set — the same truncated-gossip-table regen defect as
#13. The turn-in line never
existed, so the reward gate was never asked. Table widened to 5 slots (slot 3 = turn-in
line 0x5c, pinned by the quest's own gate; flavor slots left empty rather than
invented) + 7 Kashya chain marks for one-log diagnosis.

  • Field-proven — the owner closed the issue 2026-11-02, the same day.
  • Gates 311 → 320; self-ID Vanilla+0.0.7-R85.
  • R88 note: upstream later recovered the retail-exact 6-slot table (with the flavor
    lines the fork had left empty); the hand-build was retired at R88, notes kept.

R86 — Vanilla+ 0.0.7-R86 — 2026-11-02 — tag R86 @ 3ca2da40

The -nointro boot switch.

d2vp.exe -nointro skips the boot intro videos — the Blizzard / Blizzard North logo
.biks that play on every launch plus the auto-played title/first-run cinematics — by
never entering cutscene mode: both boot/title entries take the retail begin-failed path
straight to the next screen. Writes a [vp] cmdline -nointro mark to d2boot.log.
In-game quest cutscenes are unaffected; boot without the switch is byte-for-byte
vanilla.

  • Field-verified 2026-11-02 — "R86 verified, -nointro works" (SMOKE §K items 39–40).
  • Gates 320 → 326; self-ID Vanilla+0.0.7-R86.

R87 — Vanilla+ 0.0.7-R87 — 2026-11-02 — tag R87 @ 486b936c

The first upstream sync of the 0.0.7 line — merge b2937091: upstream 18 commits,
Ghidra DB 1806 → 1839, byte match 6,029 → 6,232 of 14,642 functions (18.40% → 19.50% of
bytes). Vanilla+ intact on top.

What came in:

  • Ghidra 1807–1813 regen rounds (packet/roster/monster/subtile parameters,
    SkillDesc/OOG types, zero-init/signed compares) and generator rounds (loop gate +
    signed division, folded-store arm order, range tests as lo <= x && x <= hi).

  • The VC8 harness + CI deps (upstream PR jaenster#32); dtchitt issue jaenster#37–jaenster#76 names; names for
    3,500 variables/fields + Storm PowerPC names + the new D2Hell file.

  • Real behavior fixes: roster party ids uint16_t throughout (joining a game no longer
    hangs in the party-grouping loop); three value-bug fixes (wide char literal, byte-mask
    select, Win32 calls shadowed by thunks) with VC8 near-miss type fixes.

  • Merge-side latent fix: DRAW_ShouldDrawEdges had returned 0 unconditionally since the
    0.0.6 merge port — wide modes never drew level edges; caught and restored during
    resolution.

  • Field-run green — "Finally, builds, runs, no regressions." Gates 326/326.

R88 — Vanilla+ 0.0.7-R88 — merge 1d401785; tag after field verify

The second upstream sync — upstream 9 commits (c8445e73..bc47c6bc), Ghidra DB
1839 → 1851, byte match 6,232 → 6,242 of 14,642 functions (19.50% → 19.54% of bytes);
22 conflicts / 27 hunks resolved, Vanilla+ intact on top.

Synced:

  • Types/prototypes from Commit-Will's, Niehztog's and Nugwa628's proposals; the third
    naming round with Mac cross-check types (CLIENTMODE_WaitForQServerConnection,
    MAINMENU_OnPressSkipEmailAddress, Objects_InitFnNN_<role>, StaticInit_gpsz*).
  • QUESTLOG_HitTestCloseButton returns bool; affix rollers take bSpawnableOnly, not
    bIsSuffix; fnGetDatabaseFileTime is __fastcall(FILETIME *);
    D2Sha1ContextStrc is 0x60 bytes.

The supersession ledger opens — upstream recovered the retail forms of two fork
fixes; the fork takes them ("upstream wins") and keeps the root-cause notes in code:

  • The R54/R85 gossip hand-tables (#13
    / #22): upstream's
    bc47c6bc restored the retail tables verbatim — A1Q1 8 / A1Q2 6 / A2Q1 9 slots —
    plus the flavor string ids the fork had left empty rather than invent. All 39
    aNpcGossipData externs are now sized retail-exact (28 were unsized pre-merge): the
    ~17-quest singular-table watch (track J) resolves wholesale.
  • vanilla-plus fix 16 (Defect 13: SFX silent, music OK): upstream's
    D2FloatIntUnion is the same root cause in the retail-faithful form (.fValue
    store, integer .nValue read-back).
  • Sound constants: upstream's exact decoded decimals
    (9.999999747378752e-05 = the float32 0.0001 promotion) replace the fork's
    spellings; the -2000.0 centibel diagnosis stays (upstream ships the same scale).

Checked and not superseded: the issue #11 [glide fix 11] hook — still fork-side
(re-planted at the R87 merge); the glide3x.dll wrapper ships from the Glide3xVK
branch, which upstream does not carry.

  • Gates: 10 stale expectations updated to the superseding state with R87-merge notes
    (epsilon ×4, the -2000.0 cast, gossip sizes ×6, Bloodraven 0x5c ×2 — retail
    carries bMenu 0 and bMenu 2 variants); self-ID row pinned Vanilla+0.0.7-R88.
    Suite 326/326.

Full Changelog: R87...R88

D2LoD Vanilla+0.0.7-R87

Pre-release

Choose a tag to compare

@VTSTech VTSTech released this 02 Nov 22:48

Merge upstream Ghidra Recovery 1807-1839

Full Changelog: R86...R87

D2LoD Vanilla+0.0.7-R86

Pre-release

Choose a tag to compare

@VTSTech VTSTech released this 02 Nov 09:16

Added -nointro command line parameter

D2LoD Vanilla+0.0.7-R85

Pre-release

Choose a tag to compare

@VTSTech VTSTech released this 02 Nov 08:37

Closes #22

D2LoD Vanilla+0.0.7-R84

Pre-release

Choose a tag to compare

@VTSTech VTSTech released this 02 Nov 07:36

Closes #16

D2LoD Vanilla+0.0.7-R83

Pre-release

Choose a tag to compare

@VTSTech VTSTech released this 02 Nov 04:51
image image image

Vanilla+ 0.0.7 — Release Notes: R77 → R83

Seven rounds, 2026-11-01 → 2026-11-02. One stash-tab polish round (R77), three upstream Ghidra-recovery syncs with zero feature changes (R78–R80, upstream 1792 → 1806), one capacity round (R82, shared stash 2 → 10 pages), and two 720p UI fixes filed and confirmed by the owner (R81 = issue #21, R83 = issue #23). The Vanilla+ gate suite grew 297 → 308 and is green at the R83 tip; every round was field-run on the Win11 build. No new d2vp.ini keys in the whole span — all six toggles unchanged, and a missing/garbage ini is still retail byte-for-byte.

Full changelog: R77...R83

Round Date Commit Type Headline
R77 2026-11-01 866883e field polish Stash tab lifted 45 px into the panel's top-right corner
R78 2026-11-02 ea0b84d + e6a31f7 upstream sync Ghidra 1794 absorbed — zero feature changes
R79 2026-11-02 f518fda + bd7a610 upstream sync Ghidra 1801 absorbed — zero feature changes
R80 2026-11-02 f427f96 + 9c8d430 upstream sync Ghidra 1806 absorbed — zero feature changes
R81 2026-11-02 3f73e56 fix (#21) Waypoint row icons fixed at 720p — "waygateicons are back"
R82 2026-11-02 988abd9 feature Shared stash grows to ten pages
R83 2026-11-02 d970fb6 fix (#23) Video-options 1280x720 label right-aligned

R77 — stash tab lifts into the panel's top-right corner

The shared-stash tab was approved horizontally at R76 but the < pager arrow's halo still kissed the gold amount text's last glyph — owner: "Looks good horizontally, but still drawing on top of the last gold character a bit with the arrow. can we move the stash label up, closer to the top right corner ?"

  • The tab row moved up 45 px (VPSHAREDUI_TabBaselineY −0x19f/−0xdb → −0x1cc/−0x108, expansion/classic) into the empty band between the panel's top edge and the retail gold display row. The R76 right anchor (+0x13c, inside the art-seam rule) is untouched.
  • The band's right side is verified-empty retail space: the coin rect and the gold-area button rect live at X +0x49..+0x96, far left of the tab; the halo top stays ≥ 7 px inside the panel edge and the click band never probes the playfield (the R69 down-walk class cannot re-open).
  • Gates 297 → 299. This is the round the R77 GitHub release shipped (tag R77 @ 866883e, carrying the whole R67→R77 shared-stash refresh).

R78 — upstream sync: Ghidra 1794 (zero feature changes)

Upstream 14f0227a absorbed (merge ea0b84d): the Ghidra v1793/v1794 regen waves + two generator rounds — split-bounds getters and per-arm calls. Upstream byte-match now 5,988 of 14,642 functions (40.9%), code 471,419 of 2,602,915 bytes (18.11%).

  • 188 upstream files changed, 10 textual conflicts (6 EOL-only; Direct3D hunks onto the gadwBitMasks regen shape; Inv wide-mode page key, QuestLog's 8 wide-offset terms and Panel's crop-draw calls re-planted; Panel was a convergence — upstream shipped the same calls the fork already carried).
  • Zero compile-fix rounds — the full battery green first try: gates 299/299, merge-site sweep 32 TUs / 0 unique errors, placement OK=46 MOVED=141 NEW=193, VP-marker census zero losses, fork TUs 4/4.
  • Upstream added its MIT LICENSE this round. Docs synced (e6a31f7, Rev 101).
  • Field verdict: "Compiles cleanly. Boots first try. No obvious regressions."

R79 — upstream sync: Ghidra 1801 (zero feature changes)

Upstream 95de360a absorbed (merge f518fda): the 1795–1801 retyping waves — widths/signedness/BOOL fields, D2ObjectInitFnArg, pointer/return types across skills, inventory, Storm and the UI, unit/game/inventory pointers where ints were declared, parameter names checked against live packet captures, and the Storm file layout. Byte-match 5,990 of 14,642 (40.9%), code 471,891 bytes (18.13%).

  • 446 upstream files, 70 unmerged paths — 62 zero-fork-delta regen TUs taken upstream-verbatim, 2 Storm-layout renames accepted, 6 manual hunks with the Vanilla+ anchors re-planted. Host shim gained the _RTL_CRITICAL_SECTION struct tag (host syntax-check only; real builds get the SDK form).
  • Zero compile-fix rounds — battery green first try: gates 299/299, sweep 46 TUs / 0 errors, fork TUs 4/4, d2boot ALL VISIBLE. Docs synced (bd7a610, Rev 102).
  • Field verdict: "Builds and Runs without error again, no regressions."

R80 — upstream sync: Ghidra 1806 (zero feature changes)

Upstream 55016505 absorbed (merge f427f96): the 1802–1806 waves — MONSTERAI flag output as a 4-byte BOOL, level/room/unit pointers in the DRLG path and grid helpers, DT1/DC6/path types + flag-word returns + character buffers, parameter names for monster spawn/skills/item stats/UI, then the generator round. Byte-match 6,029 of 14,642 (41.2%), code 479,019 bytes (18.40%), instructions 1,745,463 (67.1%).

  • 266 upstream files, 8 unmerged paths — 5 zero-delta regen TUs upstream-taken, 3 manual hunks (QuestLog site-5 a zero-edit replant — the fork line already spelled upstream's new shape; Waypoint's wide-Y term re-planted on the ternary reshape; Direct3D's UploadTextureToCache onto the typed DC6Block* with the fix-22 halt-dump and fix-27 LUT stamp re-planted). Host shim PE structs renamed to _SHIM aliases.
  • Zero compile-fix rounds — battery green first try: gates 299/299, sweep 39 TUs / 0 errors, continuity census zero losses. Docs synced (9c8d430, Rev 103).
  • Field verdict: "Great job, another clean merge. builds, runs. no regressions."

R81 — waypoint row icons fixed at 720p (issue #21, closed)

Owner filed "[720p] Art not showing on Waypoints Panel" (narrowed to the per-waypoint button icons). Root cause, code-pinned: in DRAW_UI_Waypoint every top-anchored Y carried the site-6 wide-Y term from the 720p retrofit — except the two waygateicons row draws, which kept the vanilla decompile shape byte-identical since the initial recovery. At 720p the panel art, texts and hit zones ride +120 px while the icons stayed at retail Y: all nine row icons rendered ~120 px above their buttons (rows 0–5 fully above the panel), while clicks still landed — reading as "icons not showing".

  • Fix: + VPRES_GetWideUiOffsetY() + the // VP: [resolution site-6] marker on both draws. At 800×600 the offset is 0 — retail stays byte-for-byte; only the widescreen modes move.
  • Gates: site-6: waypoint Y shifts 10 → 12 (relabeled "(R81)"); 299/299.
  • Field verdict: "Great job waygateicons are back" — issue #21 closed.

R82 — shared stash: ten pages

Owner: "Let's increase the shared stash pages to 10 for R82" — the widening the .sss v2 format reserved room for back at R75 (the original roadmap said "If that works we'll do 10 pages. Then 100.").

  • 2 → 10 shared pages. Same VPS2 magic + version — only pageCount and the per-page size/checksum pair table grow: header 28 → 92 bytes (12 + 8/page). The two fixed page ingests became one per-page loop (page-1's verdict still drives the .bak chase; later pages degrade to empty).
  • Read-back chain: v1 files (one page) → page 1; pre-R82 v2 files (two pages) → pages 3–10 start empty (logged: v2 file has %d pages - pages %d..%d start empty (pre-R82 file)); the next save rewrites all ten. A file carrying more pages than the build holds is rejected whole, untouched, with a mark — it needs a newer binary.
  • Pager labels come from a bounds-guarded literal table (Shared … Shared 10); the arrows still step one page, the word still toggles personal↔shared-1, and there is one shared gold pool across all ten. Character .d2s saves stay retail-pure (the I1 invariant).
  • Gates 299 → 306 (7 new R82 rows + the ingest-helper count re-pin + self-id bump); fork TUs 4/4 host-compiled.
  • Field: the ten-page build boots and runs (the R83 fix was field-run on it); a dedicated ten-page pager pass is on the SMOKE list (§H items 33–34).

R83 — video-options "1280x720" label right-aligned (issue #23, closed)

Owner: "the literal resolution text '1280x720' in the video options is not aligned with the video options menu … everything else is correct at 720p — except that text." Screenshot-measured: the label ran a full label width (~100 px) right of the value column and floated ~4 px above the neighboring images' ink line.

  • Root cause (two engine conventions): DRAW_EscMenu draws the row's value images with alignment 2 — cell RIGHT edge on the anchor X — while the label text left-anchored at that same X; and DRAW_text's y anchors the glyph cell bottom (digit ink ~6 px above it) while the retail value DC6s bottom-anchor at the row bottom with ~4 px of baked padding under their ink.
  • Fix: right-align via the rendered advance width (DRAW_text0, the same metric the renderer advances by) and draw at row bottom + 2 (RESLABEL_DESCENDER_COMP), putting the ink at row bottom − 4 — exactly on the HIGH/ON baseline. The row-band math was already exact; the misanchor was purely in the text call, so the fix is resolution-independent — 800×600 picks up the same corrected placement.
  • Gates 306 → 308 (the two #23 anchor pins + self-id bump); fork TUs 4/4; the edited body additionally host-compile-checked via a stub harness.
  • Field verdict: "Great job. Text is aligned now." — issue #23 closed.

Upg...

Read more

D2LoD Vanilla+0.0.7-R82

Pre-release

Choose a tag to compare

@VTSTech VTSTech released this 02 Nov 03:44

Shared Stash now has 10 pages

Full Changelog: R80...R82