Closed gibbed closed 1 year ago
Oh, wow. That's actually the best method I've seen. It does involve a bit of renaming of game content, which is not ideal, but not deal-breaking. If the MS Store launcher is happy to give the magic "can launch this" state to our token and launch a third party process, then we can launch with full control.
Thanks! I will keep this in mind if MS Store support gets added later. It's not going to happen right now, as trying to support two versions at once would suck for development (especially early development where we're just getting the basics going).
For other people reading this, key word to notice:
Hey, better response than I expected! 👍🏻
Not a huge deal on not initially having support, since it will take time for anything big to happen anyway.
Yeah, the game pass community is doing a really bad job selling themselves right now by making all kinds of ghastly hacks and ignoring messages to take down broken things that would (for example) report the same version number to plugins for both the MS and Steam version.
Yeah, I've been curious about the best way to get SFSE working for Game Pass / Xbox App since I'm playing via that version myself. I've done a bunch of Game Pass / Xbox App modding for other games, was going to check some other things I know that would work but I found the renaming-the-exe first.
Win32 AppX packages do not have the same major restrictions as a proper classic UWP app, which is why a lot of these things are possible. For example the executables are normally protected from reads, but that protection can be removed by simply moving the executable (not copying, as that's not allowed) to another location, which will remove the protection against reading. And at that point you can just copy or move the executable back, and it'll be fully readable for other third-party apps despite its restored location...
Regarding SFSE and the way it works, the main limiter/barrier of entry is that the game need to be launched with the appropriate package identity to start up properly. If Starfield.exe
is not launched with a package identity, it restarts itself through gamelaunchhelper.exe
to ensure this is the case.
The gamelaunchhelper.exe
does things like sets up the expected environment, the package identity, as well as syncs save files with the cloud before finally launching the game executable.
This requirement of going through gamelaunchhelper.exe
can be worked around through primarily two different methods:
The previously mentioned method of using a proxy executable, so gamelaunchhelper.exe
launches a proxy Starfield.exe
which then launches sfse_loader.exe
which launches the real renamed game executable. The downside of this approach is that it does not survive game updates and needs to be manually restored after each one of those.
The other alternative is to skip gamelaunchhelper.exe
entirely by using one of the debugging tools available that creates a new process in the context of a package app, such as Invoke-CommandInDesktopPackage, with the downside of cloud sync being skipped entirely.
The below PowerShell script makes use of Invoke-CommandInDesktopPackage to load a skfse_loader.exe
stored in the game folder within the context of the packaged app, which allows us to retain the game executable filename and makes it compatible across patches (but again, without cloud sync).
sfse_loader.ps1
# Basic setup:
$AppxName = "BethesdaSoftworks.ProjectGold"
$ExecutableCustom = 'sfse_loader.exe' # Leave empty if not using custom executable
# The index of the application that the executable should be launched in the context of
# This will be 0 for most games as they only have a single launch option, but a few games define separate launch
# options in their appxmanifest.xml files, where the first entry (0) might not correspond to the game/desired context
$AppIndex = 0
# Setup
$Package = Get-AppxPackage $AppxName
$PackageFamilyName = $Package.PackageFamilyName
$InstallLocation = $Package.InstallLocation
$XmlManifest = Select-Xml -Path "$InstallLocation\appxmanifest.xml" -XPath '/'
$Applications = $XmlManifest.Node.Package.Applications.Application
$AppId = if ($null -eq $Applications.Count) { $Applications.Id } else { $Applications[$AppIndex].Id }
$Executable = if ($null -eq $Applications.Count) { $Applications.Executable } else { $Applications[$AppIndex].Executable }
$Command = if ($null -eq $ExecutableCustom -or [string]::IsNullOrEmpty($ExecutableCustom)) { $Executable } else { $ExecutableCustom }
# Fix executables stored in the install folder
if ((Test-Path $Command -PathType leaf) -eq $false)
{
if ((Test-Path "$InstallLocation\$Command" -PathType leaf))
{
$Command = "$InstallLocation\$Command"
}
}
# Launch
$params = @{
AppId = $AppId
PackageFamilyName = $PackageFamilyName
Command = $Command
}
Invoke-CommandInDesktopPackage @params
Since PowerShell script executions are typically disabled on systems by default, a helper batch file can be used to circumvent that:
sfse_loader.bat
@CD /D "%~dp0"
@powershell.exe -ExecutionPolicy Unrestricted -File "%~dp0\sfse_loader.ps1"
The main downside of this approach is that as per Microsoft's documentation there's no guarantee being made about the behaviour of the created process, so there might be minor behaviour changes though from my testing I haven't noticed any (probably because AppX Win32 games run with "full trust" privileges anyway).
Thanks, that is a good description of the current restrictions. Including a powershell script and the standard workaround for enabling powershell is probably going to be a death sentence from virus scanners, though. I will look at the implementation of Invoke-CommandInDesktopPackage to see if it can be lifted or reimplemented without setting off alarm bells.
I've also wondered what specifically is breaking IPackageDebugSettings - it works fine for all of the other packaged things on the system, but seems to have exceptions for things delivered through the Xbox section of the store. Haven't done a complete debug session on it yet, but did get pretty deep.
I've also taken a look at gamelaunchhelper's helper dll, but since it's delivered as part of the OS, its implementation can change at any time. That is actually one of the bigger concerns with anything involving the MS store - the things we are doing to launch could break at any time and there's very little we can do about it.
I recognize that you're not too keen on Game Pass / Xbox App support due to the limitations of the UWP sandbox.
I did a little experiment.
It turns out that in a Starfield install in the Xbox app, you can rename
Starfield.exe
. This actually surprised me.I renamed
Starfield.exe
toStarfield.real.exe
and I wrote a thin wrapper exe to stand-in forStarfield.exe
that spawnssfse_loader.exe -altexe Starfield.real.exe
from within the UWP sandbox.It... shockingly, worked. And logs got created just fine.
Documents\My Games\Starfield\SFSE\Logs\skse_loader.txt
Documents\My Games\Starfield\SFSE\Logs\sfse.txt
Obviously this will break once build-specific stuff is added to SFSE.
But this does mean
sfse_loader.exe
can function within the UWP sandbox just fine. So if you're willing to support the UWP build of Starfield or accept contributions of the necessary information, it could happen.