-
Notifications
You must be signed in to change notification settings - Fork 83
Updated drm handling so every exe does not need to be unpacked #420
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this PR aiming to reduce the number of exe to be processed by Steamless? the changes only make differences to whether to run it, but the number of exes does not change (as I agree to the logic to run it tough,
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, it aims to reduce the number of exes, and also sometimes Steamless doesn't work - people report errors. This should work in all situations. Just worried it might break. |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -242,14 +242,14 @@ object SteamUtils { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| backupSteamclientFiles(context, steamAppId) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val imageFs = ImageFs.find(context) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val downloaded = File(imageFs.getFilesDir(), "experimental-drm-20260101.tzst") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val downloaded = File(imageFs.getFilesDir(), "experimental-drm-20260116.tzst") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TarCompressorUtils.extract( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TarCompressorUtils.Type.ZSTD, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| downloaded, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| imageFs.getRootDir(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| putBackSteamDlls(appDirPath) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| restoreUnpackedExecutable(context, steamAppId) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| restoreOriginalExecutable(context, steamAppId) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Get ticket and pass to ensureSteamSettings | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val ticketBase64 = SteamService.instance?.getEncryptedAppTicketBase64(steamAppId) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -336,6 +336,7 @@ object SteamUtils { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [Injection] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| IgnoreLoaderArchDifference=1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DllsToInjectFolder=extra_dlls | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So this injection is missing before?
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In new version after this PR, without running Steamless, we will be able to launch games because we are loading the extra_dlls which contains a new dll: StubDrm64.dll |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """.trimIndent(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -756,28 +757,28 @@ object SteamUtils { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val imageFs = ImageFs.find(context) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val dosDevicesPath = File(imageFs.wineprefix, "dosdevices/a:") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dosDevicesPath.walkTopDown().maxDepth(10).firstOrNull { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| it.isFile && it.name.endsWith(".original.exe", ignoreCase = true) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }?.let { file -> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val origPath = file.toPath() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val originalPath = origPath.parent.resolve(origPath.name.removeSuffix(".original.exe")) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Timber.i("Found ${origPath.name} at ${origPath.absolutePathString()}, restoring...") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dosDevicesPath.walkTopDown().maxDepth(10) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .filter { it.isFile && it.name.endsWith(".original.exe", ignoreCase = true) } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .forEach { file -> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val origPath = file.toPath() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val originalPath = origPath.parent.resolve(origPath.name.removeSuffix(".original.exe")) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Timber.i("Found ${origPath.name} at ${origPath.absolutePathString()}, restoring...") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Delete the current exe if it exists | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (Files.exists(originalPath)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Files.delete(originalPath) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Delete the current exe if it exists | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (Files.exists(originalPath)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Files.delete(originalPath) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Copy the backup back to the original location | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Files.copy(origPath, originalPath) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Copy the backup back to the original location | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Files.copy(origPath, originalPath) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Timber.i("Restored ${originalPath.fileName} from backup") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| restoredCount++ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (e: IOException) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Timber.w(e, "Failed to restore ${file.name} from backup") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Timber.i("Restored ${originalPath.fileName} from backup") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| restoredCount++ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (e: IOException) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Timber.w(e, "Failed to restore ${file.name} from backup") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+760
to
+780
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Case sensitivity mismatch between filter and suffix removal. The filter uses Proposed fix dosDevicesPath.walkTopDown().maxDepth(10)
.filter { it.isFile && it.name.endsWith(".original.exe", ignoreCase = true) }
.forEach { file ->
try {
val origPath = file.toPath()
- val originalPath = origPath.parent.resolve(origPath.name.removeSuffix(".original.exe"))
+ val baseName = origPath.name.let { name ->
+ val suffixIndex = name.lastIndexOf(".original.exe", ignoreCase = true)
+ if (suffixIndex > 0) name.substring(0, suffixIndex) else name
+ }
+ val originalPath = origPath.parent.resolve(baseName)
Timber.i("Found ${origPath.name} at ${origPath.absolutePathString()}, restoring...")📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Timber.i("Finished restoreOriginalExecutable for appId: $steamAppId. Restored $restoredCount executable(s)") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -225,9 +225,13 @@ class SteamUtilsFileSearchTest { | |||||||||||||||
| val dosDevicesPath = File(imageFs.wineprefix, "dosdevices/a:") | ||||||||||||||||
| dosDevicesPath.mkdirs() | ||||||||||||||||
|
|
||||||||||||||||
| // Create .original.exe file | ||||||||||||||||
| // Create multiple .original.exe files in different folders | ||||||||||||||||
| val origExeFile = File(dosDevicesPath, "game.exe.original.exe") | ||||||||||||||||
| origExeFile.writeBytes("original exe content".toByteArray()) | ||||||||||||||||
| val nestedDir = File(dosDevicesPath, "bin") | ||||||||||||||||
| nestedDir.mkdirs() | ||||||||||||||||
| val origExeFile2 = File(nestedDir, "game2.exe.original.exe") | ||||||||||||||||
| origExeFile2.writeBytes("original exe content 2".toByteArray()) | ||||||||||||||||
|
|
||||||||||||||||
| // Call the actual function | ||||||||||||||||
| SteamUtils.restoreOriginalExecutable(context, steamAppId) | ||||||||||||||||
|
|
@@ -237,6 +241,10 @@ class SteamUtilsFileSearchTest { | |||||||||||||||
| assertTrue("Should restore exe to original location", restoredFile.exists()) | ||||||||||||||||
| assertEquals("Restored content should match backup", | ||||||||||||||||
| "original exe content", restoredFile.readText()) | ||||||||||||||||
| val restoredFile2 = File(nestedDir, "game2.exe") | ||||||||||||||||
| assertTrue("Should restore exe to original location in subdirectory", restoredFile2.exists()) | ||||||||||||||||
| assertEquals("Restored content should match backup for second exe", | ||||||||||||||||
| "original exe content 2", restoredFile2.readText()) | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| @Test | ||||||||||||||||
|
|
@@ -645,7 +653,7 @@ class SteamUtilsFileSearchTest { | |||||||||||||||
|
|
||||||||||||||||
| // Verify game.exe is NOT overwritten after first replaceSteamClientDll call | ||||||||||||||||
| assertEquals("game.exe should be overwritten after replaceSteamClientDll", | ||||||||||||||||
| "unpacked exe content", gameExe.readText()) | ||||||||||||||||
| "original exe content", gameExe.readText()) | ||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: Inconsistent assertion message: The comment says 'NOT overwritten' but the assertion message says 'should be overwritten'. Compare with the similar fix at line 770 where the message was correctly updated to 'should not be overwritten'. This makes test failures confusing to debug. Prompt for AI agents |
||||||||||||||||
|
|
||||||||||||||||
|
Comment on lines
654
to
657
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix assertion message to match the new expectation. 💡 Suggested tweak- assertEquals("game.exe should be overwritten after replaceSteamClientDll",
+ assertEquals("game.exe should NOT be overwritten after replaceSteamClientDll",
"original exe content", gameExe.readText())📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||
| // Verify marker was set | ||||||||||||||||
| assertTrue("Should add STEAM_COLDCLIENT_USED marker", | ||||||||||||||||
|
|
@@ -762,8 +770,8 @@ class SteamUtilsFileSearchTest { | |||||||||||||||
| steamAppId.toString(), steamAppIdFile.readText().trim()) | ||||||||||||||||
|
|
||||||||||||||||
| // Verify game.exe is NOT overwritten after second replaceSteamClientDll call | ||||||||||||||||
| assertEquals("game.exe should be overwritten after second replaceSteamClientDll", | ||||||||||||||||
| "unpacked exe content", gameExe.readText()) | ||||||||||||||||
| assertEquals("game.exe should not be overwritten after second replaceSteamClientDll", | ||||||||||||||||
| "original exe content", gameExe.readText()) | ||||||||||||||||
|
|
||||||||||||||||
| // Verify marker was set | ||||||||||||||||
| assertTrue("Should add STEAM_COLDCLIENT_USED marker", | ||||||||||||||||
|
|
@@ -871,7 +879,7 @@ class SteamUtilsFileSearchTest { | |||||||||||||||
|
|
||||||||||||||||
| // Verify game.exe is NOT overwritten after first replaceSteamClientDll call | ||||||||||||||||
| assertEquals("game.exe should not be overwritten after replaceSteamClientDll", | ||||||||||||||||
| "unpacked exe content", gameExe.readText()) | ||||||||||||||||
| "original exe content", gameExe.readText()) | ||||||||||||||||
|
|
||||||||||||||||
| // Verify marker was set | ||||||||||||||||
| assertTrue("Should add STEAM_COLDCLIENT_USED marker", | ||||||||||||||||
|
|
@@ -917,8 +925,8 @@ class SteamUtilsFileSearchTest { | |||||||||||||||
| SteamUtils.replaceSteamclientDll(context, testAppId) | ||||||||||||||||
|
|
||||||||||||||||
| // Verify restoreUnpackedExecutable overwrites game.exe with game.exe.unpacked.exe content | ||||||||||||||||
| assertEquals("game.exe should be overwritten with game.exe.unpacked.exe content after second replaceSteamClientDll", | ||||||||||||||||
| "unpacked exe content", gameExe.readText()) | ||||||||||||||||
| assertEquals("game.exe should be overwritten with game.exe.original.exe content after second replaceSteamClientDll", | ||||||||||||||||
| "original exe content", gameExe.readText()) | ||||||||||||||||
|
Comment on lines
927
to
+929
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Update the test comment to reflect original.exe restoration. 💡 Suggested tweak- // Verify restoreUnpackedExecutable overwrites game.exe with game.exe.unpacked.exe content
+ // Verify restoreOriginalExecutable overwrites game.exe with game.exe.original.exe content🤖 Prompt for AI Agents |
||||||||||||||||
|
|
||||||||||||||||
| // Verify steam_settings folder still exists next to steamclient.dll in Steam directory | ||||||||||||||||
| assertTrue("steam_settings folder should still exist in Steam directory", | ||||||||||||||||
|
|
||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Compared the files inside two version, old version have
steamclient_extra_x32.dllandsteamclient_extra_x64.dllwould you want to delete them?Btw I don't know what is the source of these dlls can't give much comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the new tzst, those two files don't exist, only the new .dll for stubbing. I tried with one game and it worked ok.
The files come from experimental_steamclient build of gbe-fork