Add docs/COMPLIANCE.md with the project's compatibility scope: no DRM/anti-cheat circumvention, no third-party game assets, and neutral terminology for issues and PRs. Link it from README and NOTICE.
The patch comments and the Mach-O strings filter named an anti-cheat product. Use neutral wording; the patches still differ only in comments. The platform-identity document now says the overrides are for compatibility, not a bypass of anti-cheat, telemetry, licensing or platform controls.
Consolidate the non-affiliation note into a dedicated Trademarks section, replace the embedded gameplay video with a pointer to the status document, and reword the takedown note as a continuity statement. Describe the compatibility tools as referring to public API names and constants.
The bundled darling-lol.svg/png are the League of Legends logo, a Riot Games trademark, used as the project icon. The README already states that the project is not affiliated with or endorsed by Riot Games, so the icon should not be someone else's mark.
Replace both files with an original D monogram. Same file names, so flake.nix and the desktop entry keep working. The mark is provisional and easy to swap for a final one. No functional changes.
Under the rootless NixOS launcher darlingserver cannot raise its hard
RLIMIT_NOFILE to nr_open, so it kept the soft limit it inherited. Every
named memory entry holds a memfd in darlingserver, and its descriptors
peak at about 1100 when the League lobby opens. With an inherited soft
limit of 1024, memfd_create failed with EMFILE, mach_make_memory_entry_64
returned KERN_RESOURCE_SHORTAGE, and Chromium's CHECK in
PlatformSharedMemoryRegion::Create killed the League UX and the Riot
Client renderer after clicking Play.
When raising the hard limit fails, raise the soft limit to the inherited
hard limit instead. Log errno, size and fd limits when named-entry
creation fails, and log the live memfd count every 1024 creations so a
leak shows up in dserver.log.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The Riot Client UI intermittently stayed black for 30s to 2+ minutes
(sometimes indefinitely). Electron 22 / Chrome 108 verifies the local
Riot backend's TLS certificate through SecTrust, which calls trustd over
XPC. trustd is launched on demand and has EnablePressuredExit, so it is
often not running; under Darling the on-demand launch can take minutes,
and every cert verification (serialized behind Chrome's global lock)
waits for it. The UI's websocket handshake stalls after ServerHello
until then.
Start trustd at boot and keep it alive. Measured on one machine:
before, time to "renderer socket connected to Foundation" ranged
0.8s-136s or never; after, 0.83s / 0.85s / 0.97s on three launches.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_014cgmCWUB2zNH4uiMEioafC
Open with no row selected passed nil to -_setFilename:, and NSOpenPanel boxed it in an
array literal, so the action threw before the modal session was stopped and the panel
stayed up. Both buttons now go through one helper that stops the session only when
this panel is the modal window and always orders the panel out; Open accepts the
selection (filtered by canChooseFiles/canChooseDirectories and multiple-selection),
or the shown directory for directory choosers. Escape cancels.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Restack and makeKey no longer map a window AppKit considers hidden, and
setIsVisible: NO always unmaps, so the client's splash stays hidden.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Synchronize Motif decoration hints on style and titlebar-property changes, including native-window recreation and restoring ordinary WM decorations. Add a ten-case standalone Cocoa/X11 regression probe and document validation on KWin/Xwayland.
#79 made update.sh stop Darling again after the overlays and run
configure-darling-platform.py --replace-known-defaults --write. The
rootless update test still expected the old call list and failed. Stub the
identity tool, expect the stop + identity calls last, and check a failed
install never reaches them.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The issue #75 trace shows recording now runs, but Vivox's playback unit
(mic test loopback, other players' voices) sets interleaved Float32 stereo
at 32 kHz on input scope element 0 and got -10868. Apply the relaxed rule
to both client sides (input scope element 0, output scope element 1); the
playback path already interleaves for the device and PulseAudio resamples.
AudioUnitRender(bus 1) now traces frames and peak level (no samples) so a
log shows whether the client pulls sound or silence. The input check also
sets Vivox's playback format and expects unsigned 16-bit to be refused.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
RenderBus pads missing frames with zeros, which is loud for unsigned PCM
(silence is 0x80 for 8-bit, 0x8000 for 16-bit). Reject unsigned and 8-bit
formats on element 1; voice engines use float or signed 16-bit.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
When install-runtime.sh creates the prefix (first-time setup, regular or
Nix), it now runs configure-darling-platform.py --provision --write once
the runtime is stopped, so each new install gets its own synthetic serial,
MLB, UUID and ROM. A prefix counts as new the same way Darling decides it:
the directory did not exist before the first `darling shell`. Existing
prefixes keep their identity on reinstall and update.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Older setups shipped serial C02ZL0GVMD6N and UUID
6F3B2A1E-8C4D-4E5F-9A7B-1D2C3E4F5A6B to every install. After installing,
update.sh now runs configure-darling-platform.py --replace-known-defaults,
which provisions the prefix only when its saved identity still has one of
those values. Other custom values (imported serials/UUIDs, model, board,
manufacturer, ROM, MLB) are kept; prefixes with no saved identity or only
custom values are not touched.
provision() also drops a standalone system-id or provisioning_UDID derived
from the shared UUID instead of keeping it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Vivox sets interleaved Float32 stereo on output scope element 1 and
AUBase's canonical-only rule rejected it with -10868, so voice chat never
started recording (issue #75 trace: 20 attempts, all failing there).
A real AUHAL converts any linear PCM; element 1 now accepts native-endian
float32 or 8/16/32-bit integers in either layout, which PulseAudio records
and RenderBus copies. Playback (element 0) keeps the canonical rule.
The input check gains a Vivox-style run: interleaved stereo 44.1 kHz with
the device set on element 1.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
last_close started at 0.0 and the cooldown compares it with
time.monotonic(), which counts from boot. For the first 30 s of uptime
every close was refused as "in cooldown". That made the tests flaky on
freshly booted CI runners (seen on PR #76). Use None for "never closed".
Co-Authored-By: Claude Opus 5.5 <[email protected]>