Commit Graph
14 Commits
Author SHA1 Message Date
pkuzicandClaude Opus 5.5 853c09f44d Merge upstream/main (samwhosung/benilla b17be271) into the graphics programme
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 21:28:31 +01:00
Claude 98b0909d7f MONKEY (presets): farclip ceiling 777 -> 1497 for Modern fog's longer view
FARCLIP_RANGE now ends at FARCLIP_MAX = 1497 (the 1.12 slider grid of 60
carried to n = 22), a documented deviation: Modern fog already stretches the
fog end past 777 with farclip, so a longer view is visible. Terrain residency,
the model/WMO and particle walls follow farclip; at 1497 residency is at most
7x7 ADT tiles against 777's 5x5, which is the memory bound. The art-scope
sweep radius rises to 7 tiles to stay clear of the widest resident reach.

Verified: cargo test -p benilla-world --lib (643 passed). Built on Linux only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Toc8dZYuTKW1JWBFbMb5S1
2026-09-25 18:00:24 +00:00
Sam SungandClaude Opus 5.5 fe16ed14b3 String literals in benilla-ui, -world and -formats carry no record numbers (#299)
Part of #92, for `benilla-ui`, `benilla-world` and `benilla-formats`.

- 88 string literals drop private record and bug numbers, the dates of private incidents, and the workspace's name for the maintainer. They are assert and panic texts, log and printout lines, the `--` comments of the Lua prelude and of test fixtures, and one Lua assert. Each keeps its fact in its own words.
- Two test names lose their numbers: `burning_steppes_lava_builds_a_magma_surface_at_the_reported_pin` and `join_channel_by_name_answers_the_row_custom_and_nil_legs`.
- A test-only event, `B271_PROBE`, is now `ERROR_PROBE` in the two crates that register and fire it. A fixture's error text in `benilla-app`'s `ui_script` tests drops its bug number, together with the assertion that reads it.
- Doc comments that named a client function by a disassembler's label (`FUN_0068a830`) now give its address, in `benilla-formats`, `benilla-assets` and one `benilla-app` file.
- Every literal change keeps each literal's line count, proven with comments stripped and every literal masked. The two renamed tests differ only in their names.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 17:01:02 +07:00
Sam SungandClaude Opus 5.5 87a92eb295 Comments in benilla-world: one line of fact each, no history, no record numbers (#121)
Part of #41: the comments of `benilla-world`, Rust and WGSL, are rewritten to the rule in `docs/METHOD.md`, which is what the code does and the reference fact behind it, in a line. 24,226 comment lines become 8,863.

- **The mechanical strip.** The citations that were only a private record number go first, and each edit is shown to be a pure removal.
- **Wrong facts corrected.** The rewrite corrects the comments that stated wrong facts. Among them:
  - `0x6b62e0` is the WMO group's liquid renderer, not a doodad drawer.
  - The reference creates a WMO's props once, when a group enters its streaming window (`0x698720` → `0x695aa0`). It then admits them each frame the portal walk visits the group (`0x685d70` → `0x6838f0`). The old text had them created per visible group.
  - The liquid query's comments now state the reference's order: the map-object leg first, then the ADT (`0x69b6d0`). They no longer call the Outdoors/Inside split a match.
  - The interior probe runs from the character, not the camera.
  - The reference lights ground clutter. The old comment said it draws unlit.
  - The model-particle "pool order" deviation was wrong. Each instance is its own mesh, depth-sorted every frame.
  - The reference's vertical field of view follows the aspect ratio (44.1° at 16:9). The comment now gives it beside our fixed 45°.
  - The effect shader's far wall is the live `farclip`, 177 to 777 yd, not a fixed 777 yd.
  - Dozens more turned up on the way: renamed or deleted items, docs sitting on the wrong item, stale counts and links.
- **Deviation labels.** "Deviation:" now marks only a choice with a reason. An unbuilt behaviour says so plainly.
- **Verification.** Every file strips to identical code, and `cargo fmt --check` is clean. Five second readers compared every file old against new, restored the facts the rewrite had dropped, and checked each new citation against the reference.

Defects the rewrite surfaced outside the comments are filed as their own issues (#106, #114, #115, #116). The comments here state what the code does. String literals are untouched; they are #92.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 17:43:40 +07:00
Sam SungandClaude Opus 5.5 7b66dac9db comments cite the reference by address, not by private note (#30)
Comments that pointed into the maintainer's private reverse-engineering notes (a note by name, a
path, a section or finding id, the analysis's own name for a client function, a process word) now
carry the fact itself, cited by the reference client's address, by vmangos file and line, or as
"the reference". Nobody outside could follow those pointers.

Comment text only, plus the test-assert and log strings that carried the same pointers. No claim
changes: a comment the notes have since corrected keeps its wording here, and correcting it is
separate work.

The two reference generators, `scripts/gen-reference-globals.py` and
`scripts/gen-reference-verb-events.py`, named the private notes' layout to find their inputs. They
now take the input files as arguments (`--capture`, `--framexml`, `--names`, `--extents`,
`--disasm`). Run on the same inputs, both write the committed tables row for row; only the two
header lines that named the old environment variable change.

Checked per file:
- the code is identical: each file with its comments stripped compares equal before and after; a
  changed string literal is compared under a mask that proves only literal text moved and every
  literal kept its line count;
- no client address the old text cited was dropped;
- a second reviewer checked every added address against its derivation;
- a detector for the notes' names, paths, ids, function names and process words finds none left;
- `scripts/gates.sh` is green.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 12:14:08 +07:00
SamandClaude Fable 5.1 3b084ba052 pfUI's hdgraphic runs, the plates settle, and the water camera comes out
- pfUI's hdgraphic module runs: SetWorldDetail and GetWorldDetail are real verbs with the reference's three stops, and the near clip plane is a live setting at 0.100 yd rather than a frozen 0.111 (2163)
- nameplates stop drawing a black box on hover or click, stop jittering a frame behind a moving creature, and a unit that walks into range later gets its plate; a unit with no level wears no skull, and the wheel zooms over a plate (2168)
- the faint one-pixel box around every letter of a magnified overhead name is gone, each glyph now carrying its own transparent padding; interface text drawn at 1:1 is byte-identical (2169)
- the camera's water collision comes back out for now: its pivot corridor dropped the camera a yard in one frame at head depth, which is the snapping reported around the surface while swimming (2165)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-11 21:02:02 +07:00
SamandClaude Fable 5 a48441bca8 trilinear ships on, and every line of text rounds once
- the texture filter is the reference's policy — two globals, one process-wide mode, no per-texture override — registered as real CVars every sampler reads: the hardcoded trilinear + aniso 8 at five sampler sites had been read off an apitrace of an install whose `Config.wtf` set `anisotropic "16"`, a configured value taken for a default; and `trilinear` ships ON, because the registrar's `"0"` is not what a fresh install renders at — first-launch hardware detection overwrites sixteen video CVars from its hardware table, both rows a real GPU can reach set trilinear, and the reference's own `gx.log` on this machine names that row — while `anisotropic` is not among the sixteen, so anisotropy stays off
- the MSAA device clamp ran before the config was read, so a saved `gxMultisample = 8` carried from a machine that offers it still killed the render thread on one that stops at 4; the ceiling is now a property of the write itself, covering the config file, `SetCVar`, the dropdown and any writer added later — and an empty device list is no opinion, so headless runs pass through
- one line, one rounding: at a fractional display scale the per-glyph snap's f32 round-trip moved half-pixel ties by an ulp, so caps and ascenders rounded up while x-height letters stayed — the letters left the baseline, the thing the reporter photographed; the line's two anchors now round once and each glyph adds integer device-pixel offsets, so a line cannot be anything but flat at any scale, proven over 15,680 layouts — and `$WOW_DPI`'s size guard, which compared a physical request against the logical size and refused every non-1x run, now reads the unit it is denominated in
- a test that panics while holding `ENV_LOCK` no longer poisons the tests behind it — one missing knob resource had reported as twelve red tests, eleven naming the mutex and none naming the bug; there is nothing for the poison to protect, since the guard's `Drop` restores the environment during the panicking test's own unwind

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 15:15:45 +07:00
SamandClaude Fable 5 6b2a75e8a0 instruments for motion at the glass, and a macro hovers to its name
- the jitter meter measures the palette and the pixels, not just the pose: `pal` probes the rows the vertex stage actually blends (the old bone columns read a matrix the GPU never sees), `SCREEN` carries them to viewport pixels by the shader's own arithmetic, `camrot` watches the camera's rotation where only its translation had been vouching for "bit-stable", and `WOW_JITTER_RAW` dumps one bone's series unaggregated — rotations too, since a translation can be smooth while its frames are not
- `WOW_FIXED_DT=<ms>` pins the animation advance so a screenshot burst measures the render rather than its own stall — arming on the wall clock, because during load the app runs ~385 updates a second and a pinned clock reached "90 seconds" in 14 s, photographing an empty world
- `benilla-visual flow` estimates the whole window's motion by least squares over every pixel (noise floor 0.0000 px on static regions, and its brightness-constancy limit is measured and stated: invalid on a lit deforming body), `edge` reads a silhouette's sub-pixel crossing renormalised against the lighting with an honest ±0.5 px floor, `WOW_TWIST_GAP` pins a yaw gap so the body counter-twist is exercised at all — every earlier "removing it changed nothing" had measured a pass that never ran — and `WOW_DITHER` adds the dither the frame's 8-bit output has never had, off by default because the reference's framebuffer was undithered
- hovering a MACRO action slot shows one white line, its name — the reference's macro leg renders exactly that and no more, in its "normal" white, where ours was a `_ => Ok(())` from before macros shipped; and `WOW_MSAA=8` is refused with a loud warning instead of panicking the render thread, through one parser both world-camera spawners now share

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 15:14:35 +07:00
SamandClaude Fable 5 bf7201f4d3 action-bar hover stops re-deriving, and multisampling asks the GPU
- hovering the action bars re-derived the whole layout graph and hovering bags did not: `GameTooltip:SetOwner(owner, "ANCHOR_NONE")` dropped the tooltip's anchors through the conservative whole-graph derive, and with `UberTooltips` at its shipped default every action-bar button routes through that arm while a bag slot anchors `ANCHOR_RIGHT` and never does — the arm now retargets to the empty target set, and derive frames fall from 15.9 % of hovered frames to 0.2 %
- `gxMultisample` clamps to what the GPU actually offers: Apple GPUs stop at 4x, so a typed 8 was a wgpu validation panic on frame one — the clamp intersects the supported counts of every format the client multisamples into and steps the request down the way the reference's device-init retry loop does, with a warning that says so
- the Multisampling dropdown lands on the Graphics page with the device's own stops, built from the same enumeration that clamps a typed value on the reference's three bindings (`GetMultisampleFormats`, `GetCurrentMultisampleFormat`, `SetMultisampleFormat`) — a fixed Off/2x/4x/8x ladder would put a crash on the menu of every GPU that stops at 4
- capture hardening: a run whose `$WOW_WIN` the display clamped is refused in ~2 s instead of producing a wrong-sized shot to diff, a capture never reads the OS pointer (a cursor resting over the window arms a hover and a tooltip that a cursor an inch to the left does not), and the stall sampler writes into `benilla-config` instead of a hand-built `~/Library/Logs` path

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 15:13:27 +07:00
SamandClaude Fable 5 17a47acd71 borderless fullscreen ships, and the 4x MSAA nobody chose is off
- the display mode is borderless fullscreen by default, and there is no exclusive mode at all — winit ignores exclusive on Wayland, X11's path cannot restore the desktop after a crash, macOS has none, and WoW itself dropped it in 8.0.1; 1.12's `gxWindow` row keeps its name, polarity and default with "0" redefined as borderless, read before the window exists so it is born in the player's mode (a window that does not fill gamescope's nested output is a documented input break, and the recorded workaround is "set the game to fullscreen"), `gxResolution` remembers the windowed size, and the Graphics page grows 1.12's own Windowed Mode checkbox
- the UI camera says `Msaa::Off` out loud, because silence there meant Bevy's default 4×: the world arrives on this camera as an already-resolved quad and everything it draws itself is axis-aligned rects, so four samples bought a 4× colour target, a 4× depth texture nothing ever writes, 4× the fill on every quad and a resolve — for a measured difference of MAE ≤ 0.024, all of it quad borders now drawn at their authored crispness, which is also the reference's hard-edged 8-bit direction
- `gxMultisample` is a real player setting, and it ships off — the reference's own default: the reference registers no literal, it formats field 21 of the `VideoHardware.dbc` row the GPU matched, a 193-row table that holds nothing above 2 anywhere and whose every 2004-era id misses a modern card, so the fallback rows answer and all of them hold 1; the setting persists, all three world-lane cameras read it on the reference's [1,16] scale rounded down the way its own retry loop steps, and `$WOW_MSAA` survives session-only
- two instruments for the tooltip hunt: `rebuild_ui_mesh` — which sorts, clips and re-splits every quad in the interface on any dirty frame — gets a meter carrying total/sort/split/write beside the script phases whose flat reading had stood as an alibi, and `WOW_PROBE_HOVER` sweeps the real cursor across named frames through the real pointer path, pressing nothing: the hover recorder records what a hand does, and this supplies the hand

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 15:12:37 +07:00
SamandClaude Fable 5 7146bc91f0 the login scene frames its art, char select remembers, DXT stays DXT
- the glue scene widens only as far as its art goes: none of the seven login dioramas is drawn wider than about 3:2 — measured per texel by `benilla-extract glueextent`, which rasterises every batch into the camera's own tan-space, painting where the reference's alpha-key test passes — so the frame zooms down to the reference's own 16:9 opening (never tighter) and pillarboxes past the aspect the art cannot fill, instead of showing the clear colour past the backdrop's slanted edges; 4:3 stays byte-identical
- the character screen opens on whoever you last logged in as: the reference's `lastCharacterIndex` CVar, written at Enter World and only there — clicks and arrow keys never touch it, which is what makes the value mean "last logged in" rather than "last clicked" — restored on every character-list rebuild and clamped into range
- spam-hovering tooltips stops costing 2 ms: two write sites gave up naming their node and re-derived the whole layout graph (1,812 µs against the ledger's 44, on 919 of 1,262 resolves) — the wrap pin now touches the one region it wrote, and re-pointing a tooltip at the button under the cursor retargets the node's edges in place instead of throwing the cached graph away
- two corrections off the project's first GPU-bound report (a Steam Deck at 94% GPU busy on 8.4 W of a 15 W budget, the memory-stall signature): `farclip` ships the reference's registered 350 instead of the clamp's 777 — the value also sizes terrain residency, so 777 streamed, held and drew 4.8× the area — and BLP textures upload WoW's own DXT blocks verbatim the way the reference does, instead of decoding to RGBA8 at 8× the bytes of DXT1; the terrain slider still reaches 777, and the lanes that read texels on the CPU (terrain arrays, the character-skin compositor) stay decoded and say why

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 15:11:59 +07:00
SamandClaude Fable 5 da786b9e59 Terrain Distance returns to Graphics, and guards flag your map
- the Terrain Distance slider is back on Options → Graphics, in its 1.12 seat and range (177–777, live, no Apply) — and it now drives how much world is resident, not just how far you see: the streamer derives its resident and prefetch windows from farclip in the reference's own chunk units, pulling the ring in as you drag left and streaming it back one tile per frame as you drag right; the `WOW_TILE_RADIUS` env var, the debug panel's farclip slider and a dressed-up fog constant all retire into it
- ask a city guard for directions and the destination lands on your maps: `SMSG_GOSSIP_POI` becomes a red flag drawn through the same landmark path as towns and inns — an icon in place when near, competing for a rim arrow when off the edge — and the world map's landmark enumeration answers now, so the flag renders there too and names itself on hover
- the flag is one slot (new directions replace the last), drops itself within 10 yards of the destination, expires after the reference's own 480 seconds, and clears on any world entry; the rim-arrow rank rides the packet's own field, not a guessed constant

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 18:18:30 +07:00
SamandClaude Fable 5 ad2a1fb2d1 Quiver loads, teleports stop losing the city, the camera eases right
- Quiver works end to end (the reported nil-field error): 1.12's widget method tables are flat, so the 19 Region methods are ONE function per name — a frame's `GetHeight` IS the texture's — where we had two implementations behind two disjoint registries; `Button:SetFontString` and the Set/GetMin/MaxResize quad land with it, and the 219-addon survey moves loads-without-error 150 → 151 with every other addon byte-identical
- a teleport stops dropping you into a bare city: the reveal gate now waits on geometry that can actually draw (14 regions had sat undrawn for 630 ms with the cover already down), a relocating snap ≥100 yd raises the cover, and the pipeline warm pass runs once per process — a far same-map teleport's cover drops 3.8 s → 0.8 s
- the empty-world flash on a fully-resident teleport dies with it: the camera's world pose publishes before anything in Update reads it, so the visibility verdict stops being computed up to 644 yd from the eye — the lag reads 0 yd on every snap frame of every arm
- the camera follow becomes the engine's own curve — an edge-armed cosine smoothstep clamped to 0.1–2 s behind a 7-state input classifier, the enum 0/1/2 with Smart staying the default — and overlapping chat bubbles stack as whole cards, one frame level per bubble, nearest to the camera on top

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-21 18:10:46 +07:00
SamandClaude Fable 5 bdef9cd790 benilla-world: the engine becomes its own crate
- the world engine splits from the game into a benilla-world crate — 112 files, and the wall is ratcheted to zero names of the game inside the engine
- the engine's public doorway is counted and gated at 32 items, and the render materials, shaders and asset cache move down to benilla-assets
- the game's files leave the engine's asset root — game:// is its own space — and a spike binary boots the engine with no game attached
- weather rides along: snowfall emission is denominated in the reference's frame cap, and a long teleport retires the stranded precipitation field instead of leaving it behind

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-11 18:13:44 +07:00