Programming & Technical Aug 15, 2026

Steamworks SDK 1.65 - Replace IsRunningOnSteamDeck Without Breaking Settings 2026

Migrate Steamworks SDK 1.65 without breaking settings - replace IsRunningOnSteamDeck, split diagnostic vs functional calls, test Proton and hardware defaults, report performance safely.

By GamineAI Team

Steamworks SDK 1.65 - Replace IsRunningOnSteamDeck Without Breaking Settings 2026

Pixel art of a handheld PC hardware compatibility check for a Steamworks SDK 1.65 migration

If you are searching steamworks sdk 1.65 after Valve's July 24, 2026 release, the useful question is not "what is in the changelog?" - the useful question is a pipeline decision: will removing IsRunningOnSteamDeck() break your graphics defaults, input paths, or QA telemetry, and can you migrate to the new hardware and Proton APIs without hard-coding the next device name into production settings?

Valve's Steamworks SDK 1.65 announcement is the authoritative release note. Godot teams should also read GodotSteam's 4.21 / SDK 1.65 post, which shipped wrapper support a few days later. An announcement is a ceiling. This tutorial is a floor test: one evening, one disposable branch, a migration matrix that separates diagnostics from functional settings, and a rollback-safe receipt.

This article turns the 1.65 list into an S1-S6 keep/hold lab. You will inventory every IsRunningOnSteamDeck call, reclassify each as diagnostic or functional, swap diagnostics to IsRunningOnSteamHardware(), move functional defaults to GetSteamHardwareDefaultConfig() (and capability checks like Big Picture / VR / Proton), decide whether to report performance settings, check Steam Input origins and wrapper readiness, and write steamworks_sdk_1_65_migration_receipt_v1.json. You will not rewrite your whole Steamworks layer tonight.

Non-repetition: this is not Your First Proton 11 Steam Deck Verify Pass, which is a one-evening Proton runtime verify. It is not Steam Machine Verified - what indies should lock, which is a cert-lane readiness guide. This URL owns one intent: migrate SDK 1.65 so device-name branches stop driving settings, without breaking what players already tuned.

Audience Start here Done when
Beginner / solo indie Glossary, Monday ritual, S1-S3 Deck/Machine defaults still apply without IsRunningOnSteamDeck
Working developer S1-S6, wrapper matrix, receipt Compile + smoke on Deck and desktop; telemetry is opt-in only
Company / pipeline lead CapEx four-liner + hold criteria Named owner, rollback branch, no silent privacy surprises
Creator / QA Share note + verification tools list Discord paste replaces "SDK updated, hope it works"

Time estimate: 90-150 minutes for one game branch. Add 30 minutes if you must bump GodotSteam / Steamworks.NET and re-smoke Editor init.

Default recommendation: keep SDK 1.65 for any title that still calls IsRunningOnSteamDeck() for graphics, UI scale, or input - the API is removed, so staying on 1.64 is a ticking compile break. Hold shipping a live depot until S4-S5 prove your functional settings still resolve on Deck hardware and under Proton, and until privacy review signs off on any new performance reporting.

What SDK 1.65 actually changed

Strip the secondary-blog paraphrases and keep Valve's functional intent.

Steam Machine, Steam Frame, and Steam Deck

  1. Removed ISteamUtils::IsRunningOnSteamDeck(). Do not call it. Do not #ifdef around it forever.
  2. Added ISteamUtils::IsRunningOnSteamHardware() → returns ESteamHardwareType. Valve's guidance: use this for analytics, support, or diagnostic purposes. For functional decisions, use other SDK calls.
  3. Added ISteamUtils::GetSteamHardwareDefaultConfig() to help choose default video (and other) settings tuned for specific Steam hardware - and to let future hardware change those defaults without a recompile.
  4. Added ISteamUtils::IsRunningUnderProton() to detect the Proton compatibility layer on Linux.
  5. Pre-existing helpers that still matter when replacing Deck checks: IsSteamInBigPictureMode(), IsSteamRunningInVR(), and other feature-specific utils.

ISteamApps - performance reporting (opt-in data)

  1. Added SetGamePerformanceSetting() and SetGameRenderResolution() so a game can report relative performance settings and resolution to Steam. That data is included with anonymous framerate data if the user has opted in to sharing it. Treat this as telemetry you choose to send - not a free always-on sensor.

ISteamUGC

  1. New query/rank options: k_EUGCQuery_RankedByNumParentItems and k_EUGCRankedByNumParentCollections (descending order by dependents / collections). Metadata max also moved (GodotSteam notes 10,000).

Steam Input

  1. New action origin enum values for Switch 2, Steam Controller, and Steam Frame Controller.

ISteamMatchmakingServers

  1. ServerFriends() - friends who recently played a specific server.
  2. "popularamongfriends" filter - servers friends commonly play on.

The two lines a pipeline lead must read twice: device-name checks are for diagnostics, and default configs are for settings. Mixing them is how you ship "Steam Machine looks like Deck Ultra" bugs six months from now.

The diagnostic vs functional rule (print this)

Intent Wrong (1.64 habit) Right (1.65)
Crash report / support ticket / analytics dimension IsRunningOnSteamDeck() IsRunningOnSteamHardware() → store ESteamHardwareType
First-run graphics preset, UI scale, FSR default, TDP-friendly quality if (IsRunningOnSteamDeck()) ApplyDeckPreset() GetSteamHardwareDefaultConfig() + your tuned preset table; capability checks for Big Picture / VR / Proton when needed
"Are we under Proton?" (shader cache, path quirks, crash notes) Guess from OS alone IsRunningUnderProton()
"Should we show controller glyphs?" Device name Steam Input action origins / Big Picture / active controller
"Should we send graphics setting telemetry?" Always Only with user opt-in path; call SetGamePerformanceSetting / SetGameRenderResolution when you mean to

If a call changes what the player sees or how the game runs, it is functional. If a call only changes what you log, it is diagnostic. Never collapse those into one bool isDeck.

Monday ritual - inventory, reclassify, smoke, decide

Minute Action Evidence Keep or hold
0-15 Record SDK version, wrapper version, branch name, AppID Session header in receipt Hold if you cannot name a rollback tag
15-40 Grep every IsRunningOnSteamDeck / Deck bool Inventory table (S1) Hold ship if any functional call is unmarked
40-70 Replace diagnostics with IsRunningOnSteamHardware Diff + sample log line S2
70-100 Move settings to GetSteamHardwareDefaultConfig (+ Proton/Big Picture as needed) First-run presets on Deck + desktop S3
100-120 Decide performance reporting; wire only if privacy OK Opt-in note S4
120-150 Wrapper readiness + Input origins + smoke under Proton Matrix + S5/S6 Adopt or hold depot

If you only have 90 minutes, finish S1-S3. A clean settings migration without telemetry is a real ship gate.

Company CapEx four-liner

  1. Scope - one disposable branch upgrades to SDK 1.65 / matching wrapper; no live depot promote until S5 smoke passes.
  2. Cost - Steamworks SDK itself is free for partners; cost is engineer time (half day) plus any wrapper bump / CI rebuild. GodotSteam 4.21 already tracks 1.65; Unity Steamworks.NET may lag - budget a wrapper wait if bindings are missing.
  3. Trap - calling SetGamePerformanceSetting / SetGameRenderResolution without confirming the anonymous framerate opt-in story, or using IsRunningOnSteamHardware to drive graphics (device names return for future hardware you have not tuned).
  4. Owner - one named engineer owns the inventory, the settings matrix, privacy sign-off for telemetry, and the rollback tag.

Prerequisites

  • [ ] Partner Steamworks access and a non-shipping branch / AppID test build.
  • [ ] Ability to grep the whole repo for IsRunningOnSteamDeck, SteamDeck, is_deck, bSteamDeck.
  • [ ] At least one Steam Deck (or Deck-class) device and one desktop Windows build for comparison.
  • [ ] Optional but strong: a Proton path (Deck desktop mode / SteamOS) to exercise IsRunningUnderProton().
  • [ ] Wrapper inventory: native C++ Steamworks, GodotSteam version, Steamworks.NET / Facepunch version.
  • [ ] Read Valve's release note and, if on Godot, the GodotSteam 4.21 post.

Beginner glossary

  • IsRunningOnSteamDeck: removed API that returned a boolean for Steam Deck. Do not use it.
  • IsRunningOnSteamHardware: returns an enum of Steam hardware types - for analytics/support/diagnostics, not for "set Ultra because Deck."
  • GetSteamHardwareDefaultConfig: asks Steam for a default configuration hint tuned to the hardware - preferred for first-run settings, including future devices without a rebuild.
  • IsRunningUnderProton: true when the Windows build is running under Proton on Linux.
  • Diagnostic vs functional: logs vs player-facing behavior. Split them.
  • Anonymous framerate data: Steam's opt-in player telemetry channel; 1.65 can attach performance setting + resolution if you report them.

S1-S6 - the migration in detail

S1 - Inventory every Deck branch

Search the codebase and build scripts:

IsRunningOnSteamDeck
SteamUtils()->IsRunningOnSteamDeck
is_steam_deck
IsSteamDeck
STEAM_DECK
bRunningOnDeck

Build a table:

File:line Current behavior Diagnostic or functional? Replacement candidate
GraphicsBootstrap.cpp:88 forces "Deck Medium" preset functional GetSteamHardwareDefaultConfig + preset map
CrashReporter.cpp:40 adds deck=1 tag diagnostic IsRunningOnSteamHardware
InputGlyphs.cpp:12 swaps to Deck glyphs functional Steam Input origins / Big Picture

Pass S1 when every call is classified. Unclassified calls are automatic hold.

S2 - Move diagnostics to IsRunningOnSteamHardware

For crash reports, support zips, analytics dimensions, and Discord paste for QA:

// Diagnostic only - do not drive graphics from this enum alone
ESteamHardwareType hw = SteamUtils()->IsRunningOnSteamHardware();
crash_fields["steam_hardware"] = SteamHardwareTypeToString(hw);
crash_fields["proton"] = SteamUtils()->IsRunningUnderProton() ? "1" : "0";
crash_fields["big_picture"] = SteamUtils()->IsSteamInBigPictureMode() ? "1" : "0";

Map the enum to a stable string in your code. Do not invent device names Steam has not published in your logging schema without a documented unknown bucket.

Pass S2 when a Deck build and a desktop build both emit a hardware field, and no diagnostic path still calls the removed API.

S3 - Move functional settings to default config + capabilities

Replace first-run and "force Deck preset" logic with:

  1. Ask GetSteamHardwareDefaultConfig() for the Steam-provided default hint.
  2. Map that hint to your tuned preset table (Low / Medium / High / Deck-tuned / Machine-tuned).
  3. Layer capability checks: Big Picture, VR, touch, and IsRunningUnderProton() only where the capability actually changes behavior (e.g. shader cache paths, not "make it look like Deck").
  4. Preserve player overrides. First-run defaults must not clobber a user who already set Ultra.

Pseudocode:

if (!UserHasSavedGraphicsProfile()) {
  auto cfg = SteamUtils()->GetSteamHardwareDefaultConfig();
  ApplyPreset(MapSteamDefaultToOurPreset(cfg));
}
// Never: if (IsRunningOnSteamHardware() == k_ESteamHardwareType_SteamDeck) ApplyDeckUltra();

Pass S3 when:

  • Fresh profile on Deck-class hardware lands on your intended preset.
  • Fresh profile on desktop does not get the Deck preset.
  • An existing saved profile is left alone.
  • Future-hardware comment exists in the preset map: unknown configs fall back safely (usually desktop Medium), not to a hard-coded Deck Ultra.

This is the backlink magnet. Changelog blogs stop at "API added." You ship a settings contract.

S4 - Performance reporting (optional, privacy-gated)

If - and only if - your privacy policy and Steam opt-in story allow it, report current relative performance setting and render resolution via SetGamePerformanceSetting / SetGameRenderResolution when those values change. Valve attaches them to anonymous framerate data when the user has opted in.

Do:

  • Call when the player changes quality or resolution, not every frame.
  • Document the fields in your privacy / data note for partners.
  • Gate behind the same opt-in expectation Steam already uses for framerate sharing.

Do not:

  • Treat the APIs as required for Deck Verified.
  • Send personally identifying data through them.
  • Assume every player opted in.

Pass S4 when either (a) you deliberately skip reporting and the receipt says so, or (b) reporting is wired, rate-limited, and privacy-reviewed.

S5 - Wrapper readiness + Steam Input origins

Stack 1.65 readiness (as of late July 2026) Action
Native C++ Steamworks Valve shipped 1.65 Bump SDK, fix compile breaks on removed API
GodotSteam 4.21 shipped with SDK 1.65 (Server 4.10); brief delay on Win32 DLL then fixed Upgrade plugin; re-test init and hardware calls
Steamworks.NET / Facepunch Often lags Valve by days-weeks Check bindings for new utils; stub compile guards if missing; do not ship half-bound APIs

Also smoke Steam Input origins for Switch 2 / Steam Controller / Steam Frame Controller if your glyph or binding UI switches on origin enums. Missing origins usually show as "unknown" glyphs - catch that in QA, not after review.

If Editor init fails after a wrapper bump, isolate with Steamworks init failed - Unity Editor native plugin path.

Pass S5 when the wrapper you ship actually exposes the calls you use, and a controller-origin smoke list is checked.

S6 - Proton + hardware smoke and share note

Run a short matrix:

Build Check Expected
Windows desktop Fresh graphics profile Desktop preset, not Deck
Steam Deck (Game Mode) Fresh profile + Big Picture Hardware default maps to your Deck-tuned preset
Same Deck under Proton path IsRunningUnderProton true in diagnostics Settings still from default-config path, not from a Proton bool
Existing save Launch after upgrade Player overrides preserved
Crash zip Hardware enum present No IsRunningOnSteamDeck symbol

For Deck verify tooling beyond this API smoke, keep 14 free Steam Deck verification tools after Proton 11 and the evening Proton 11 verify pass in the QA kit. For Machine cert language, pair with Steam Machine Verified. Broader integration bookmarks live in 18 free Steamworks and PC distribution resources.

Share note:

SDK 1.65 migration (YYYY-MM-DD)
Branch: [name]  Wrapper: [native / GodotSteam x.y / SW.NET]
S1 inventory: N calls (D diagnostic / F functional)
S2 hardware enum in crash/analytics: pass/fail
S3 default-config presets Deck vs desktop: pass/fail
S4 performance reporting: skipped / privacy-OK wired
S5 wrapper + input origins: pass/fail
S6 Proton + save preserve: pass/fail
Decision: promote depot / hold

Pass S6 when the note and receipt exist with a named owner.

Migration matrix you can copy

Old pattern New pattern Notes
if (IsRunningOnSteamDeck()) quality = Medium GetSteamHardwareDefaultConfig() → map to Medium Future hardware can change without rebuild
if (IsRunningOnSteamDeck()) log "deck" IsRunningOnSteamHardware() Diagnostic
if (Linux) assume Proton IsRunningUnderProton() Accurate on Deck desktop vs native Linux builds
Glyphs from device name Steam Input action origins Includes new Controller / Frame / Switch 2 origins
Always send graphics telemetry Opt-in + SetGamePerformanceSetting / SetGameRenderResolution Privacy gate
Hard-code Steam Machine later Prefer default-config + unknown fallback Do not invent a new device bool every SKU

Who should hold the depot

  • Teams with functional Deck bools still in production - compile may break the moment you bump; finish S1-S3 on a branch first.
  • Unity / C# wrappers without 1.65 bindings yet - hold the feature use of new APIs; you can still remove Deck calls behind stubs if compile forces it, but do not fake GetSteamHardwareDefaultConfig.
  • Anyone wiring performance reporting without privacy review - skip S4 reporting until legal/comms agrees.
  • Titles mid-Deck Verified resubmit - finish the current cert packet on a known SDK, then migrate on the next packet (unless the removed API already blocks you).

Common mistakes

  • Replacing IsRunningOnSteamDeck with IsRunningOnSteamHardware == Deck for graphics. That recreates the device-name problem for Steam Machine / Frame / future SKUs.
  • Clobbering saved player settings on first boot after upgrade.
  • Assuming Proton from OS alone and changing shader or path logic incorrectly.
  • Shipping half-updated wrappers where headers compile but runtime symbols differ (especially after GodotSteam's Win32 DLL hiccup - re-verify your platform binaries).
  • Calling performance setters every frame.
  • Skipping desktop control. A Deck-only smoke cannot prove you did not break desktop defaults.

Troubleshooting order

  1. Compile break on IsRunningOnSteamDeck - you still have a caller; finish S1.
  2. Wrong preset on Deck - check default-config mapping and whether a leftover device bool still wins.
  3. Desktop gets Deck preset - mapping table or first-run flag is wrong; compare fresh profiles.
  4. Proton flag never true - confirm you are actually under Proton; native Linux builds will correctly return false.
  5. Wrapper missing symbols - check GodotSteam / Steamworks.NET version; pin known-good DLLs per platform.
  6. Editor init failed after bump - plugin path / steam_appid.txt; see the help article linked in S5.

What teams should do next Monday

Solo indie

  • Grep, classify, migrate S2-S3 on a branch.
  • Smoke Deck + desktop once; promote when S6 passes.

Small studio

  • One engineer owns the inventory spreadsheet.
  • QA owns the S6 matrix; pipeline lead owns privacy for S4.

Company / publisher build

  • Require the migration receipt in the release checklist.
  • Ban new device-name conditionals in code review.
  • Track wrapper versions next to SDK version in the SBOM / dependency note.

Creator / content QA

  • Paste the share note into Discord after the smoke.
  • Attach one screenshot of first-run presets on Deck vs desktop.

Key takeaways

  1. Steamworks SDK 1.65 (July 24, 2026) removes IsRunningOnSteamDeck() - migrate before the next SDK bump forces it.
  2. Use IsRunningOnSteamHardware() for analytics/support/diagnostics only (Valve announcement).
  3. Use GetSteamHardwareDefaultConfig() for first-run and hardware-tuned defaults - including future Steam hardware without a recompile.
  4. Use IsRunningUnderProton() instead of guessing from OS.
  5. Keep diagnostic vs functional calls separate - never one bool isDeck for both.
  6. SetGamePerformanceSetting / SetGameRenderResolution attach to anonymous framerate data only when the user opted in - privacy-gate them.
  7. GodotSteam 4.21 tracks SDK 1.65 (GodotSteam post); confirm your C# wrapper bindings before calling new APIs.
  8. New Steam Input origins (Switch 2, Steam Controller, Steam Frame Controller) need a glyph/QA pass.
  9. Preserve player-saved settings across the upgrade.
  10. Smoke Deck + desktop + Proton path before promoting a depot.
  11. Hold the depot if wrappers, privacy, or preset mapping are incomplete.
  12. A filled migration matrix + receipt is the cite-worthy artifact - not another changelog summary.

FAQ - Steamworks SDK 1.65

What happened to IsRunningOnSteamDeck in SDK 1.65?

It was removed. Valve directs developers to feature-specific methods: IsRunningOnSteamHardware for diagnostics, GetSteamHardwareDefaultConfig for settings, plus existing helpers like Big Picture and VR checks, and the new IsRunningUnderProton.

Should I use IsRunningOnSteamHardware to set graphics quality?

No. Valve documents that call for analytics, support, or diagnostic purposes. For functional defaults, use GetSteamHardwareDefaultConfig and capability-based checks so future Steam hardware can change defaults without a recompile - and so you do not bake device names into gameplay settings.

What does GetSteamHardwareDefaultConfig do?

It helps choose default game settings (video and others) tuned for specific Steam hardware, and supports changing those defaults on future Steam hardware without recompiling the game. Map its result to your own preset table and keep player overrides intact.

How do I detect Proton in SDK 1.65?

Call ISteamUtils::IsRunningUnderProton(). Do not assume every Linux session is Proton, and do not drive graphics solely from the Proton flag.

Are the new performance APIs required?

No. SetGamePerformanceSetting and SetGameRenderResolution let you report settings/resolution into Steam's anonymous framerate channel when the user has opted in. Skip them until privacy and product agree.

Does GodotSteam support SDK 1.65 yet?

Yes. GodotSteam 4.21 (and GodotSteam Server 4.10) shipped with SDK 1.65 support around July 29, 2026, after a short Windows 32-bit DLL fix from Valve. Upgrade and re-test init on each target platform.

What about Steamworks.NET?

C# wrappers often lag Valve's native SDK. Confirm bindings for the new utils before calling them in production. You can still remove dead IsRunningOnSteamDeck calls while waiting, but do not stub fake hardware-default behavior.

Will this migration help Steam Machine and Steam Frame?

Yes - that is the point. Diagnostics can report hardware type; settings should come from default-config and capabilities so Machine / Frame / future devices do not require a new hard-coded branch each time.

Related reading