Skip to content

Steam: pick a game's version (beta branches), with beta codes - #490

Open
insertfloppy wants to merge 8 commits into
willfaust:mainfrom
insertfloppy:upstream/steam-versions
Open

insertfloppy wants to merge 8 commits into
willfaust:mainfrom
insertfloppy:upstream/steam-versions

Conversation

@insertfloppy

Copy link
Copy Markdown
Contributor

Requested by Cameron · project thread

Builds on #484 (Steam DLC). The same download code changed there, so this
branch sits on top of it. Until #484 is merged its 7 commits show here too.
The new commit is the last one, "Steam: pick a game's version (beta
branches), with beta codes".

Change

Game details › Steam › Version (and the download sheet) lists the public
build and the game's beta branches from PICS depots.branches. A
password-protected beta opens with Enter beta code: Steam checks the code
(ClientCheckAppBetaPassword), and its private depot section
(ClientPICSPrivateBeta, binary KeyValues) gives the branch's manifests.

Downloads, updates and repairs take the chosen branch:

  • each depot's manifest for the branch, or the public one for a depot the beta
    leaves alone;
  • the manifest request code names the branch (app_branch);
  • the install record states the branch's build and BetaKey in UserConfig and
    MountedConfig, so Valve's client keeps the game there.

An installed game on another branch gets "Download " to switch, and the
update badge compares against the recorded branch. Choices and codes are kept
per game. A beta without an accepted code stops the download instead of
quietly taking public.

Testing

  • On device (iPhone, sideloaded build): switching a game's version works.
  • Host checks: tests/host/check-steam-library.py passes on this branch
    (879 checks, with swiftc 6.1 on Linux and the two Darwin-only fcntl hints
    removed locally). It covers branch parsing, the public fallback, the
    private-branch merge, binary KeyValues, the code exchange and the record.
    It isn't compiled for iOS here.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LiLQakAySboBR7FkqkJFKS

insertfloppy and others added 8 commits October 29, 2026 06:45
The depot selection left out every depot with a dlcappid, so owned DLC
that ships as depots of the game never arrived: Fallout: New Vegas's
four Courier's Stash packs were missing from Data. A DLC depot is now
selected when the account's licenses include it, and its install
record entry names its DLC app as Valve's client writes it. An owned
DLC depot Steam still refuses a key for is skipped instead of failing
the install. Games already installed get their DLC from "Repair
installed files".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LRteDvgrjU8qVByo5Mipwz
Signed-off-by: ft7t8drgwf-wq <337626868+ft7t8drgwf-wq@users.noreply.github.com>
Game details › Steam shows the DLC the game's install record lists
(InstalledDepots entries with a dlcappid), with sizes, named from Steam
when signed in, so you can see whether owned DLC was downloaded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LRteDvgrjU8qVByo5Mipwz
Signed-off-by: ft7t8drgwf-wq <337626868+ft7t8drgwf-wq@users.noreply.github.com>
Game details showed "DLC <id>" for Fallout 4's DLC. Names are now asked
for in one request, and any still missing take the name of their depot in
the game's own app info. The lookup logs how many names it found, or why
it was skipped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LRteDvgrjU8qVByo5Mipwz
Signed-off-by: ft7t8drgwf-wq <337626868+ft7t8drgwf-wq@users.noreply.github.com>
The library refresh keeps the DLC apps of the account's licenses and
attaches each to its game (common.parent, extended.listofdlc or a depot's
dlcappid), with the depots it adds and their sizes. A download still takes
every DLC depot the account's licenses include, minus the DLC apps the
player turned off (SteamAppInfo.dlcOff from SteamDLC.offApps), by the
game's own OS, architecture and language rules.

The download sheet has a DLC section with a switch per DLC; an installed
game's page has Owned DLC (n) beside Installed DLC, and Download DLC when a
DLC left on is missing (it runs Repair). env.MADEIRA_STEAM_DLC = 0 turns
DLC off. Docs in STEAM_LIBRARY.md ("DLC"); host checks for the selection,
the owned list and the choices.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LiLQakAySboBR7FkqkJFKS
Signed-off-by: ft7t8drgwf-wq <337626868+ft7t8drgwf-wq@users.noreply.github.com>
…tated"

Old games (New Vegas) state no size for their DLC depots, so each row read
"Size not stated, not installed". A row now says Installed when the install
record names the DLC (dlcappid), with its recorded size, or holds all its
depots; otherwise "Not installed", with a size only when Steam states one.
Download DLC leaves out DLC the record already names.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QwPPpv8GktVxXz37784ajC
Signed-off-by: ft7t8drgwf-wq <337626868+ft7t8drgwf-wq@users.noreply.github.com>
The selection took a DLC depot only when a license package listed that
depot ID. New Vegas's Courier's Stash packages list the DLC apps but not
their depots, so Download DLC only re-checked the game's files. The
download now also counts the depots of the DLC apps the account owns
(the cached owned-DLC list); Steam still refuses a key for anything not
owned, and a refused DLC depot is skipped as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QwPPpv8GktVxXz37784ajC
Signed-off-by: ft7t8drgwf-wq <337626868+ft7t8drgwf-wq@users.noreply.github.com>
Valve's client records a game's sharedinstall depots (DirectX, VC++ from
Steamworks Common Redistributables, 228980) under its SharedDepots and
refuses to start it until the owner app is installed: "Failed running app
730 (required app 228980 not ready)". Madeira skipped those depots, and
Valve's client in Dock cannot fetch them ("No connection"), so CS2 and
Garry's Mod needed a Repair before every start.

The downloader now plans them too, into the owner's folder
(steamapps/common/Steamworks Shared), and records them under the game's
SharedDepots and in the owner's appmanifest, as Valve's client does. A
redistributable that cannot be planned is logged ([steam-redist] skipped)
and left out; it never fails the game's install.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QwPPpyEGW7D4dmNsNKzK6P
Signed-off-by: ft7t8drgwf-wq <337626868+ft7t8drgwf-wq@users.noreply.github.com>
Game details › Steam › Version (and the download sheet) lists the public
build and the game's beta branches from PICS depots.branches. A
password-protected beta opens with Enter beta code: Steam checks the code
(ClientCheckAppBetaPassword) and its private depot section
(ClientPICSPrivateBeta, binary KeyValues) gives the branch's manifests.

Downloads, updates and repairs take the chosen branch: each depot's
manifest for the branch, the public one for a depot the beta leaves alone,
the manifest request code names the branch (app_branch), and the install
record states the branch's build and BetaKey in UserConfig/MountedConfig so
Valve's client keeps the game there. An installed game on another branch
gets "Download <branch>" to switch; the update badge compares against the
recorded branch. Choices and codes are kept per game (SteamBranch); a beta
without an accepted code stops the download instead of taking public.

Host checks cover branch parsing, the fallback, private-branch merge,
binary KeyValues, the code exchange and the record.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QwPPpwWZUYwhTgAaZ14GMh
Signed-off-by: ft7t8drgwf-wq <337626868+ft7t8drgwf-wq@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant