Session folders, tool and installer logs and the stores' log now all live under the
app's private files/logs instead of Download/DroidDeck, and every existing "Share
logs" action bundles them into one zip that goes through a final scrub.
- Where: LinuxRuntime.logDir() = files/logs; sessions keep their dated folders and
30-session pruning, tools/ and stores/ beside them. The "Logs" setting keeps its
meaning. Game save backups stay in Download/DroidDeck/Saves.
- Migration: at first start the old session folders, tools/ and loose logs move from
Download/DroidDeck into files/logs (Saves untouched), and every moved folder is
scrubbed under the current rules.
- Scrubbing: one rule set (SecretScrub) for the stores' log and the zip. The scrub
marker carries the rules version, so a rules change re-scrubs every folder at the
next start (in the background, a few at a time). Steam login account names and
emails, account-name fields, OAuth codes, tokens in URLs and private LAN
addresses are removed; Windows exception codes and server addresses are kept.
- Share: one zip of the current session folder plus the last 7 days of stores/ and
tools/, written to cache/share and handed to the share sheet.
* Windows components: lay out installer .exe wrappers without running them
The components page could only take .msi packages apart; most catalog entries ship an
installer .exe, so VC++ runtimes, .NET Framework 4.0-4.8 and the .NET Core/5+ runtimes sat
under 'Need a Windows installer'. droiddeck-msi-install now opens those wrappers and lays
out the packages inside the same way:
- WiX bundles (Visual C++ 2012-2022, .NET Core/5+ desktop runtimes): the .wixburn section
names the containers, each a cabinet found by its header (signing moves them); payloads
get the names the bundle manifest lists, so each package finds its cab1.cab beside it.
ARM64 packages are skipped, x86 and x64 both laid out.
- Self-extracting cabinets (Visual C++ 2005-2010): cabextract, external cabinet beside the
package (vc_red.cab).
- Self-extracting 7-Zip archives (.NET Framework 4.0-4.8): 7-Zip, now bundled with the
msitools (Arch Linux ARM 7zip 26.04: 7z + its 7z.so plugin, licences beside the others).
The complete product (netfx_Full_*) wins over the 4.0 parts and the per-Windows copies.
- An .exe that is its own setup program (NSIS, InnoSetup) reports that it holds no package.
- --unpack opens an archive for the app: DirectX's redistributable for XACT's cabinet picks.
The app executes the remaining catalog steps offline: set_windows (HKCU\Software\Wine
Version), set_register_key, get_from_cab (through --unpack) and 'uninstall Wine Mono' (the
mscoree override beside it is what matters), and reads url/file_name the catalog nests under
'environment' on a few .NET entries. Setup-program installers stay in the waiting section
with a note that says what they are.
Verified on this branch's engine with msitools, cabextract and 7z: VC++ 2010 x64 (19 files,
61 values), VC++ 2022 x64 bundle (26 files, 66 values), .NET 4.0 (1053 files, 6056 values,
Framework64\v4.0.30319 with clr.dll and mscorlib.dll, NDP\v4 keys) and .NET 4.8 (1633
files, 522 GAC assemblies, 6495 values). Not yet run on a device.
* Windows components: the pressed row greys out and shows its own two-step progress bar
Pressing a switch now greys that row at once and runs a thin bar across it: the download
0..100, then the install 0..100, with a caption naming the file or the stage (a dependency's
name in front while that installs first). Turning a component off greys the row the same way
until the pick is saved. The page-wide bar at the bottom is gone; Done waits on the busy row.
droiddeck-msi-install reports how far along it is ('progress 37% placing files'): reading,
each cabinet, every 5% of files placed, the registry, done - and a wrapper maps each package
into its share, so a bundle's two packages run 10..55 and 55..100. The app parses the percent
and passes a typed Progress (component, stage, phase, percent) up to the editor.
* Windows components: the ones turned on sort to the top of the list
In 'All components' the picks for this game come first, in their usual alphabetical order
among themselves; turning one off returns it to its place. The row moves once the install has
finished and the pick is saved, not while its progress bar is running.
* Windows components: an 'Installed for this game' section under the recommendations
What is turned on for this game gets its own section between Recommended and All components,
alphabetical; the recommendations stay where they are (a recommended pick stays there). A
component in the section leaves All components, and goes back to its place when turned off.
LB/RB jump through the new section too.
A Stores section (rail, under Games; Setup › Stores gate) with each store's sign-in,
library, storefront shelves and a download queue. Each store has two tabs, Store and
Library, and Library filters to All or Installed; libraries open from a saved copy
and refresh in the background, with install sizes on every card. Games install to internal storage,
or a card chosen at Install time, and are registered in the Steam client as non-Steam
games, so they launch through Steam and droiddeck-proton from either the front end or
the client.
- Downloads: GOG, Epic and Amazon engines in Rust (app/src/main/rust/stores, built by
cargo-ndk, nothing compiled in the tree). One adaptive fetch core with a latency
brake, stalled-host handoff and every CDN a store offers. Per-stage progress,
pause/resume, two-step cancel that deletes, failed downloads kept for retry, a
foreground service with Wi-Fi and wake locks and notification controls.
- Games tab: store source chips (Steam, GOG, Epic, Amazon, Custom) and store art.
- Epic: per-launch exchange code from the app and from Steam's Play button,
"Epic sign-in (EOS)", "Launch offline", and a game's web links opened in Android's
browser for EOS consent. The EOS overlay crashed games and is left out.
- Cloud saves (GOG, Epic): pulled before launch, pushed after the game or the session
ends, no upload before a first download, conflicts never overwritten, backups both
ways.
- Logs: every store line redacted; the engine log goes to daily files.
* feat: replace the LXQt desktop with SteamOS-style KDE Plasma
* feat: leaving the KDE desktop logs out through Plasma and returns to gaming mode
* feat: DroidDeck logo wallpaper as the KDE desktop default
* feat: build the KDE wallpaper from the DroidDeck mark artwork
* ci: keep the built desktop package as a short-lived artifact for device testing
* fix: the desktop loading screen no longer promises Steam on the desktop
* docs: the output resize comments name the desktop's KWin
* fix: the desktop package verifies every package's Arch Linux ARM signature and never replaces a published tag
* fix: programs sent to the GPU from the desktop drop its software rendering overrides
* fix: an interrupted desktop install no longer counts as installed
* feat: pin the desktop package to its DroidDeck-Components release instead of the catalog
DirectAudio from its own release: driver set per Proton audio interface (CachyOS fix), the Steam client's own DirectAudio sink, binaries out of tree
Games
- Two driver sets ship from the pinned DirectAudio release (tools/directaudio/release.env =
directaudio-linux-v1.1.0, sha256-checked by tools/directaudio/fetch.sh in CI and
build_local.sh): linux-wine11 for Valve Proton 11 / Experimental / GE-Proton, and
linux-wine11-systhread for Proton-CachyOS, whose Wine carries the system-thread mmdevapi
interface. steam-compatibility picks by whether the Proton's own winepulse.so imports
PsCreateSystemThread, never by the version string (both say wine-11.0; the wrong set is
silence). No matching set: DirectAudio off, Proton's audio runs, logged.
- Proton-CachyOS's launcher pre-sets WINE_AUDIO_DRIVER=pulse,alsa and its mmdevapi reads that
before the registry (Valve's and GE's do not read it): the wrapper exports
WINE_AUDIO_DRIVER=directaudio,pulse as well as writing the registry. On CachyOS this also
makes DirectAudio engage on a game's first launch.
- A wineserver from an earlier Steam verb can save its in-memory registry over the appended
Audio value; the wrapper says so when one is live. Writing through it (wine reg add) and
creating a missing prefix first (proton run wineboot) were tried on the device and withdrawn:
a second Proton/Wine run inside Steam's launch sequence got launches aborted.
- Tests: both sets, no set, no prefix (34 pass).
Steam client audio
- DirectAudio = module-directaudio-native-sink, the game driver's AAudio engine inside the
PulseAudio daemon, one step from Android (adaptive buffer, two-burst floor, primed ring with
fades, reopen on route change, watchdog, limiter). Default. Shared output = the previous relay
route, kept. New pref clientAudioRoute; the old boolean is not read. If the native sink cannot
open its stream the daemon keeps running (.nofail) and ensureClientSink loads the plain AAudio
sink instead, logged to audio.log. Audio bundle stamp bumped.
Out of tree
- app/src/main/assets/directaudio/ is generated and ignored; tools/directaudio-relay/ and the
vendored module-directaudio-sink.c + da_relay_proto.h are gone; tools/aaudio-sink keeps only
module-aaudio-sink (the fallback). The release carries the relay and sink field fixes by
MaxsTechReview (#338), credited there and in its AUTHORS.
Device-proven on an AYANEO Pocket FIT: client sink 12 ms / 4 ms bursts, 0 underruns; FEZ on
cachyos-11.0-20261005-slr on DirectAudio (took pulse before); FEZ on Proton Experimental
unchanged; Curse of the Dead Gods on CachyOS from a cold prefix, DirectAudio on first launch.
Co-authored-by: The412Banner <the412banner@users.noreply.github.com>
The compositor takes touch and pointer positions over its whole output and
removes the letterbox bars itself, but the session sent them already
measured from the picture's edge, so the bars were taken off twice. Any
session whose output is a different shape from the panel (16:9 on a 16:10
tablet or a foldable, a fixed resolution on a wide phone) had taps and the
touchpad pointer pulled away from the centre, by up to a bar's height at
the edges: on a 2400x1504 panel showing 1280x720, a tap near the top
reached the first row and one near the bottom landed 32 rows low. Stretch
to panel hid it because that output has no bars.
Direct touch, the touchpad and mouse pointer, and the second-screen pointer
now send positions over the whole view, so the compositor's own mapping
puts them on the pixel under the finger.
* fix: keep Steam's directory listings on FUSE libraries
Before it creates, moves or deletes a content file the Steam client lists
the whole destination directory about ten times to match names
case-insensitively. On Android's FUSE storage every listing goes through
the media provider, so reserving space grew quadratically with the number
of files: 33 minutes for Haunted Paws Demo (3,938 files) in a Games folder.
The client's listings under steamapps/ on FUSE are now kept while the
directory's stat is unchanged, for at most five seconds, and patched by
the client's own creates, renames and removals. Other changes fail the
stat check and the directory is read again. BL_NO_DIR_CACHE=1 turns it off.
Haunted Paws Demo into the internal shared Games folder: reserving space
33m08s -> 25-52s, committing 6m15s -> 19-30s, install 39m50s -> 1m12s-1m51s.
Internal storage is unchanged (5s reserve).
* fix: drop stale directory listings on coarse-timestamp volumes
NTFS reports whole-second directory times and a fixed size, so a change
made outside the client's own calls could leave a cached listing stale.
Listings now carry an inotify watch and are dropped on any event the
client's own patched changes don't account for. A forked child stops
caching, since it shares the parent's queue.
Covers rewinddir, telldir and seekdir on cached listings, and directories
opened by the fast-path preload's opendir, which goes through fdopendir.
Update strings.xml
Improvements to the Japanese Translation
I have rewritten the translation to make it sound more natural in Japanese.
Also, since “Loader” in “Decky Loader” is a proper noun, I believe it does not need to be translated.
Co-authored-by: xXJsonDeruloXx <danielhimebauch@gmail.com>
Translate the 103 missing strings (screen effects, scaling, Wine sync
backends, FEX for AppImages, Steam repair, device info) and fix existing
ones: inverted meaning in mode_suspend_note, content_add_roms and
wadb_connect_address, double space in the update/install buttons,
outdated AppImage/Proton hints, "1 приложений"-style counts, gender
agreement with substituted names, lowercase fragments that are joined
into sentences, and inconsistent terms (Setup, Developer options, Stop
session, Button mapping).
Co-authored-by: xXJsonDeruloXx <danielhimebauch@gmail.com>
* Support CJK text with the device's own fonts
The Linux runtime's rootfs ships DejaVu alone, which has no CJK
glyphs, so Chinese, Japanese and Korean text in Steam Big Picture and
on the LXQt desktop draws as tofu boxes (issues #118, #206, #249).
Bind the device's own CJK fonts - Android's world-readable Noto CJK
.ttc, or DroidSansFallback / Source Han - into the guest under
/usr/share/fonts/droiddeck-cjk, so nothing is added to the ~790 MB
runtime image and the coverage follows the device. A new
droiddeck-fonts script, run by droiddeck-session before any program
that queries fontconfig, links the default rules, writes local.conf
with DejaVu first and the CJK families after it, and rebuilds the
fontconfig cache once per set of font files. The desktop's own
fontconfig block moves there, so every mode gets it.
* Fix CJK and Thai: bind the device font directory, not one file at a time
The first cut bound each device font with its own proot -b host:guest. A
per-file binding into a plain directory is not applied here: the guest sees a
zero-byte placeholder where the font should be (stat size=0, fc-scan empty),
so Chinese stayed tofu even though the app had "bound" the font. A directory
binding is what the rest of the runtime relies on, so bind /system/fonts as a
whole under /usr/share/fonts/droiddeck-device. That also brings Thai, Arabic,
Devanagari and the emoji fonts, which the runtime did not have either.
Verified on the AYN Thor: the session's fontconfig probe reports
sans=DejaVu Sans, zh=Noto Sans CJK SC, th=Noto Serif Thai, and Steam Big
Picture in Simplified Chinese renders without tofu (screenshot under
docs/development/evidence/).
---------
Co-authored-by: xXJsonDeruloXx <danielhimebauch@gmail.com>
* i18n: complete Spanish
Spanish gets the strings added since it landed and the ones that are only a format or a brand name, so it has the same keys as English, in the same order. Each English term keeps one Spanish word across the file, and a few existing strings are reworded to read right with the values they are filled with.
* i18n: use compilación for build in Spanish
* i18n: translate new strings to Spanish
---------
Co-authored-by: Kurt Himebauch <136133082+xXJSONDeruloXx@users.noreply.github.com>
Co-authored-by: xXJsonDeruloXx <danielhimebauch@gmail.com>
* feat: run a guest agent in every session for commands, focus and the Steam client's DevTools
* feat: give the agent bridge game, input, UI and experiment commands behind a Setup toggle
* feat: droiddeckctl commands for the new bridge, a scenario runner and contract tests
* feat: run cleanup steps after every scenario run so a failure cannot leak into the next
* feat: restart a session that died between scenario runs with start --reuse
* fix: give droiddeckctl stop its own, longer wait for the session's logs
* fix: harden debugging tools access and output
Steam saves a shortcut's Properties to shortcuts.vdf as soon as they
change and keeps its appid. The session rewrote every added game's entry
from the app's list before and after each client run, keeping only the
launch options, so a Target or Start In set in Steam, a new name or icon,
the hidden and overlay switches, the last played time and Steam's sort
name were all put back at the next exit.
droiddeck-steam-shortcuts now merges instead: an entry keeps every field
Steam has, and the app's exe is written only where the app changed it.
What the app last asked for and what Steam then had are recorded beside
shortcuts.vdf (.droiddeck-shortcuts.json). A Target changed in Steam to a
file inside the game's folder becomes the exe chosen in Steam > Settings >
Games, and a later pick there replaces it in Steam, so both show the same
exe. The appid now stays with the folder, so changing the exe no longer
turns the game into a new one with a new prefix, playtime and launch
options. A game whose folder is missing is set aside with its settings
and comes back with them. The exit-time merge runs before Steam's logs
are copied.
With Second library on Automatic, every writable Games folder is now a
Steam library: it gets the same private prefix and tool binds as the card,
the app hands the session the list (BL_STEAM_LIBRARIES), and
droiddeck-steam-library registers, relabels and forgets entries from it.
Steam offers them in the install dialog as "<folder> (<volume>)", and
Proton mapping, esync, the redist seeder, desktop entries and the compat
beat read every registered library instead of only the card. Games folder
libraries stop at the fast path's bind budget.
Steam's preallocation on Android's FUSE storage either failed outright
(NTFS answers EPERM, so installs were cancelled as "not enough disk
space") or zero-filled the whole download first (exFAT, minutes for a
small game). After fallocate is refused, the Steam client's ftruncate
extension of its own staging files is reported as done; the writes that
follow fill the file. A 76 MB install to a USB SSD now preallocates
instantly instead of taking about 3.5 minutes.
A library that is not there is left out of the list and forgotten until
it returns, imports whose folder is missing are set aside rather than
offered as broken installs, and the front end refreshes when storage is
mounted or removed.
A "Linux system" entry in the file manager's Storage list (the rail and the
drive menu) opens the root of the Linux system the sessions run in - the
app's files/linuxfs, the desktop's / - so its files can be browsed, copied
in and out without the desktop. Shown once the runtime is installed; Back
stops at that root like a drive's, and the drive label reads Linux system
anywhere under it. The label is translated in all nine languages.
Steam ships no CJK font and the rootfs only has DejaVu, so a phone set to
Chinese, Japanese or Korean got Steam in that language with every character
drawn as a box. Bind Android's /system/fonts into the guest, index it again
whenever it changes, and prefer the matching Noto CJK face for each language.
Opening the manager at a folder (a game's files, its Proton prefix, the
saves folder, or the picker's remembered folder) ran openDrive() on the
start dir, which pinned the up/back floor to that folder: the toolbar
arrow was greyed out and Back closed the screen. The start dir now opens
with loadDirectory(), keeping the volume-root floor computed for it, and
folders in the app's private storage (internal Steam library, prefixes)
floor at the app's files dir instead of themselves.
Adds a ".." (Up one level) row at the top of the list and grid whenever
the current folder is above its floor, sharing one goUp() with the
toolbar arrow. Covers both screens built on FileManagerScreen: the File
Manager and the in-app file/folder picker. Strings for all 9 locales.
* l10n: move hard-coded UI text into string resources (#212)
About 650 user-facing strings were written in Kotlin and Java, so no
translation could reach them and the UI stayed half English in every
language. They now live in values/strings.xml.
- Dialogs, menus, status lines, toasts and errors shown to the user go
through getString/stringResource.
- Code that matched on English text now uses IDs: installer and loading
stages, Decky stages, storage labels and the Back button's order labels.
- Choice lists (upscalers, FPS limits, textures, themes, presets) carry
@StringRes labels instead of English.
- Robolectric tests read the app's resources (includeAndroidResources).
- Six strings nothing used any more are dropped.
Existing translations are untouched; the new strings show in English
until they are translated.
* Layouts: fit longer text in other languages, and small phones
Found by screenshotting every page, tab and menu in each language on a
phone, a tablet, a 640dp phone and a foldable.
- Rail labels shrink to fit instead of being cut off (FitText).
- Tab rows tighten when they overflow and scroll the chosen tab into view.
- Menus fade over a down arrow when more entries are below, and open
scrolled to the current choice.
- On a small phone the desktop card's button moves under its title,
emulator tiles go two across, the GPU support verdict wraps and the
Updates page stacks the channels under the status.
* l10n: translate every string into Spanish, Japanese, Korean and Chinese (#187)
Simplified Chinese, Traditional Chinese (Taiwan) and Traditional Chinese
(Hong Kong, reviewed for Hong Kong wording) are complete, as are Spanish,
Japanese and Korean: no missing keys and no placeholder mismatches.
* Language setting: follow the system, or a language picked in Setup; Steam uses it too (#187)
- Setup -> Launcher starts with a Language row: "System default (...)"
and each language by its own name. With nothing picked the app follows
the system language; a pick applies at once and stays until System
default is picked again.
- Steam keeps its language in ~/.steam/registry.vdf under both
Valve/Steam/language and Valve/Steamsteamglobal/language. Before each
start of the client the guest helper droiddeck-steam-language writes
both (and exportedsettings.json), and the client gets -language.
SteamLanguage maps the app's language to Steam's names: english,
spanish/latam, japanese, koreana, schinese, tchinese.
* l10n: translate the strings main added since, and Chinese review fixes
- Translate the 32 strings added on main since (Windows components,
device details, Force SSBS, native Steam sleep) into all six languages.
- zh-CN: busy labels say what is in progress again (正在取消, 正在导出
...), as the other languages do.
- zh-CN: "set up" is 配置, as Setup is; 设置 stays for Settings.
- zh-TW: proton_compatible_note says 前綴 rather than "prefix".
About 650 user-facing strings were written in Kotlin and Java, so no
translation could reach them and the UI stayed half English in every
language. They now live in values/strings.xml.
- Dialogs, menus, status lines, toasts and errors shown to the user go
through getString/stringResource.
- Code that matched on English text now uses IDs: installer and loading
stages, Decky stages, storage labels and the Back button's order labels.
- Choice lists (upscalers, FPS limits, textures, themes, presets) carry
@StringRes labels instead of English.
- Robolectric tests read the app's resources (includeAndroidResources).
- Six strings nothing used any more are dropped.
Existing translations are untouched; the new strings show in English
until they are translated.
* Build the DirectAudio relay from source
The relay helper shipped as a prebuilt libdirectaudiorelay.so with no source in the
repo. Its source (The412Banner/directaudio @ 3548a4a, the commit the bundled driver
names in version.txt) now lives in tools/directaudio-relay, unmodified, and CI and
build_local.sh compile it into jniLibs the way proot is built. It shares
da_relay_proto.h with the PulseAudio sink, which is byte-identical to its own copy.
* DirectAudio relay: prime before playing, one consumer, safe buffer floors
- The output stream started before the client had its ring, so every connection
opened with a run of short callbacks: six clicks per stream on a RedMagic, even idle.
The callback now plays silence until the ring holds its target, and only a real
underrun afterwards counts.
- An underrun ends the block with a short fade and waits for the ring to refill to
target before resuming with a fade in, instead of zero-padding every short callback.
Each callback spent starved grows the target, so one stall sizes it for the next.
With a producer freezing 60 ms every 2 s: 14 underruns before, 1 after.
- During a reopen the outgoing and incoming streams could both drain the ring. Only
the promoted stream reads it now; any other plays silence.
- The ring target starts at 40 ms instead of two bursts (8 ms) and keeps what it
learned across reopens.
- The device buffer is at least two bursts; 12 ms was a single burst on devices that
grant a 20 ms legacy stream.
* PulseAudio: the classic path plays through the native-rate AAudio sink
The classic path loaded the prebuilt 0.1.5 module, which opened AAudio at the daemon's
default 44.1 kHz: Android gave it a legacy stream (20 ms bursts) and resampled, after
PulseAudio had already resampled the 48 kHz clients down. Its data callback also waited
on the daemon's IO thread, and it started at two bursts and grew only after an audible
underrun. The app's own module-aaudio-sink, built by CI into the same bundle, now
carries that path:
- The stream opens at the device's rate (48 kHz) with the buffer at two bursts or
30 ms, whichever is more, still growing a burst per underrun.
- A write that times out part way keeps the rest for the next write instead of
dropping it.
- A stream reopened after a route change asks for the rate the first one got, so the
sink keeps its format instead of unloading.
* Audio: DirectAudio sink at audio priority, deeper client buffers, no decay probing
- module-directaudio-sink's IO thread asks for nice -16 like module-aaudio-sink's, so
the client's producer keeps up under game load.
- PULSE_LATENCY_MSEC=60 for the session: libpulse clients under FEX (the Steam
client, winepulse when DirectAudio is off) keep enough queued to ride out a late
wakeup.
- BANNER_AUDIO_DIRECT_DECAY=0: the driver's decay shrinks the device buffer every
10 s of quiet until it underruns again, a click by design.
Both sit ahead of Downloads/droiddeck-env and per-game environment, which still win.
* Audio: drop the session-wide PULSE_LATENCY_MSEC
On an AYN Thor it took the Steam client's stream to 110 ms (60 ms tlength on top of the
sink's 40 ms) with no underruns to show for it, and the delay was audible. Clients pick
their own buffers again; the per-game option still sets it.
* PulseAudio sinks: wait in the poll loop, never in a blocking call
Clients' audio reaches a sink as messages its IO thread handles in pa_rtpoll_run. The AAudio
sink spent each iteration inside a blocking AAudioStream_write for up to a burst, and the
DirectAudio sink inside a futex wait for up to a burst, so a client's data sat unread and its
stream ran dry: a Chromium-shaped client (44.1 kHz float, 30 ms tlength, 10 ms minreq) had
304 underflows in 30 s on the AAudio sink, heard as crackling in the Steam client. Bursts of
20 ms (a legacy stream, an AYN Thor) made it worst.
- module-aaudio-sink writes without blocking, renders only what the device has room for, and
comes back after half a burst. 0 underflows in 30 s, with and without 8 busy cores.
- module-directaudio-sink tops the ring up on the same half-burst timer instead of sleeping
on the relay's futex.
* DirectAudio relay: vendor the source the shipped binary was built from
The import took 3548a4a, the commit the bundled driver names in version.txt, but the relay
binary that shipped came from e4727e9 on the same branch (feat/linux-relay-mic): its strings
match a build of that source exactly. 3548a4a has no --mic-fifo, so with the microphone on the
relay printed its usage and exited, and DirectAudio played nothing. This is e4727e9 as
published; the fixes made on top of 3548a4a follow in the next commit.
* DirectAudio relay: prime before playing, one consumer, safe buffer floors (on e4727e9)
The same changes as ca5d39b, carried onto the e4727e9 source: playback waits until the ring
holds its target, an underrun fades out and re-primes, starved callbacks grow the target, only
the promoted stream drains the ring, the ring target starts at 40 ms and survives reopens, and
the device buffer is at least two bursts.
* Steam client audio: DirectAudio by default
A fresh install plays the Steam client through the DirectAudio relay. Choosing Classic in the
Steam cog is stored and kept; only an install that never chose falls back to DirectAudio.
* Windows components: install .msi packages (XNA, PhysX, GFWL, MSXML...) without running them
droiddeck-msi-install reads a Windows Installer package's tables with msiinfo and unpacks its
cabinets with cabextract, then lays out what Wine's msiexec would have installed: files at their
64-bit Windows paths (Program Files (x86), syswow64...), .NET assemblies in the GAC, side-by-side
assemblies in winsxs, and the registry values in the view the component writes through. Conditions,
features and the folder-setting custom actions are evaluated as on Windows 10 64-bit; what needs
the package's own code (DXSETUP, self-registration) is listed in the component's notes.
droiddeck-wincomponents puts a component's drive_c tree into the prefix (keeping the prefix's own
spelling of each folder) and writes its registry values into system.reg/user.reg before launch,
following Wine's link keys (Wow6432Node\Classes, CurrentControlSet...). Turning it off puts every
value back and takes an added PATH entry out again.
The app installs these from the Windows components menu like the DLL ones: it downloads the .msi
into the runtime and runs the installer there (GuestCommand). msitools 0.106 and cabextract 1.11
come from Arch Linux ARM, pinned in tools/msitools/packages.txt and hosted on the msitools-0.106-r1
release. wine-gecko stays hidden (Proton ships it) and wine-mono keeps waiting (uninstall step).
* Windows components: open with the top switch focused, by touch or by pad
The dialog's window starts in touch mode, where a switch cannot take focus, and the first switch
was asked once, two frames after the list loaded, only when a pad opened it - racing the dialog's
own Done focus. Now it always puts the window in pad mode, holds Done while the list loads and
then asks the top switch every frame until it has focus.
* Windows components: give msitools its own libraries; show a failed install on its row
msiinfo and cabextract sit with their libraries in /usr/local/lib/droiddeck-msitools, which the
loader does not search: every .msi install stopped at "libmsi-1.0.so.0: cannot open shared
object file". droiddeck-msi-install now runs them with that folder on LD_LIBRARY_PATH.
A failed install also says so under the component itself ("Could not install: ..."), not
only at the foot of the dialog, past the list.
---------
Co-authored-by: The412Banner <the412banner@users.noreply.github.com>
* Fast path: hold every bind, so added games start in their own folder
libblfastpath kept the first 64 binds and dropped the rest without a word. A session has 87 (two
Games folders are the last two), so /root/Games/<folder>/... was mapped into the rootfs - the
empty mount point - instead of the bound storage. Wine resolves a new process's working directory
by those paths, found no drive for it and started every added game in C:\windows ("could not
find DOS drive for current working directory"): DiRT 3 did not mind, FEZ looks for
Content\Essentials.pak there and quits.
The library now holds 256, and turns itself off for the process when a bind does not fit or the
list runs past that, leaving the call to proot, which never maps it wrong. The app keeps the fast
path off for a session with more binds than that.
Verified on an AYANEO Pocket FIT: FEZ (added game) reaches its title screen; the warning is gone.
* Fast path: say in the session log when it stays off
---------
Co-authored-by: The412Banner <the412banner@users.noreply.github.com>