From 4b90b615bd2540890b20db7338207b2b58e961a8 Mon Sep 17 00:00:00 2001 From: Avasam Date: Sat, 11 Jul 2026 22:24:13 -0400 Subject: [PATCH 01/10] Try removing --upx-exclude=_winrt*.pyd --- scripts/build.ps1 | 4 +--- src/capture_method/WindowsGraphicsCaptureMethod.py | 9 ++++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/scripts/build.ps1 b/scripts/build.ps1 index 7d284609..5c7bc3cd 100644 --- a/scripts/build.ps1 +++ b/scripts/build.ps1 @@ -48,9 +48,7 @@ try { '--upx-exclude=pywintypes*.dll', '--upx-exclude=win32*.pyd', # win32comext.shell.shell -> shell.pyd (plain name, no win32 prefix) - '--upx-exclude=shell.pyd', - # winrt projection modules hit the same UPX+Wine DLL-init breakage - '--upx-exclude=_winrt*.pyd') + '--upx-exclude=shell.pyd') } else { # Missing upx executable should be enough, but let's be explicit diff --git a/src/capture_method/WindowsGraphicsCaptureMethod.py b/src/capture_method/WindowsGraphicsCaptureMethod.py index d65cafc3..b6475ae7 100644 --- a/src/capture_method/WindowsGraphicsCaptureMethod.py +++ b/src/capture_method/WindowsGraphicsCaptureMethod.py @@ -15,9 +15,6 @@ from winrt.windows.graphics.capture import Direct3D11CaptureFramePool, GraphicsCaptureSession from winrt.windows.graphics.capture.interop import create_for_window from winrt.windows.graphics.directx import DirectXPixelFormat -from winrt.windows.graphics.directx.direct3d11.interop import ( - create_direct3d11_device_from_dxgi_device, -) from winrt.windows.graphics.imaging import BitmapBufferAccessMode, SoftwareBitmap from capture_method.CaptureMethodBase import CaptureMethodBase @@ -49,6 +46,12 @@ raise IS_WGC_SUPPORTED = False # pyright: ignore[reportConstantRedefinition] +if IS_WGC_SUPPORTED: + # This pyd hard-fails to load when the d3d11 export is missing (UPX+Wine) + from winrt.windows.graphics.directx.direct3d11.interop import ( + create_direct3d11_device_from_dxgi_device, + ) + async def convert_d3d_surface_to_software_bitmap(surface: IDirect3DSurface): return await SoftwareBitmap.create_copy_from_surface_async(surface) From d069e7a89df216737fb01a659cfceba249c3dd24 Mon Sep 17 00:00:00 2001 From: Avasam Date: Sun, 12 Jul 2026 00:38:59 -0400 Subject: [PATCH 02/10] try fix pyright --- src/capture_method/WindowsGraphicsCaptureMethod.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/capture_method/WindowsGraphicsCaptureMethod.py b/src/capture_method/WindowsGraphicsCaptureMethod.py index b6475ae7..afb947d9 100644 --- a/src/capture_method/WindowsGraphicsCaptureMethod.py +++ b/src/capture_method/WindowsGraphicsCaptureMethod.py @@ -46,7 +46,7 @@ raise IS_WGC_SUPPORTED = False # pyright: ignore[reportConstantRedefinition] -if IS_WGC_SUPPORTED: +if TYPE_CHECKING or IS_WGC_SUPPORTED: # This pyd hard-fails to load when the d3d11 export is missing (UPX+Wine) from winrt.windows.graphics.directx.direct3d11.interop import ( create_direct3d11_device_from_dxgi_device, From f3085c826060d04cdfb441335dbc1fe7850e3a1e Mon Sep 17 00:00:00 2001 From: Avasam Date: Sun, 12 Jul 2026 01:07:05 -0400 Subject: [PATCH 03/10] Remove dependency on pywin32's shell and --upx-exclude=shell.pyd --- scripts/build.ps1 | 4 +--- src/AutoSplit.py | 13 +++++++------ src/error_messages.py | 2 +- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/scripts/build.ps1 b/scripts/build.ps1 index 5c7bc3cd..74c6fb62 100644 --- a/scripts/build.ps1 +++ b/scripts/build.ps1 @@ -46,9 +46,7 @@ try { # Native Windows tolerates it, Wine's loader doesn't. Exclude them from compression. '--upx-exclude=pythoncom*.dll', '--upx-exclude=pywintypes*.dll', - '--upx-exclude=win32*.pyd', - # win32comext.shell.shell -> shell.pyd (plain name, no win32 prefix) - '--upx-exclude=shell.pyd') + '--upx-exclude=win32*.pyd') } else { # Missing upx executable should be enough, but let's be explicit diff --git a/src/AutoSplit.py b/src/AutoSplit.py index 22fee6cc..42978ef1 100755 --- a/src/AutoSplit.py +++ b/src/AutoSplit.py @@ -17,8 +17,6 @@ if sys.platform == "win32": import ctypes - from win32comext.shell import shell as shell32 - def do_nothing(*_): ... # pyautogui._pyautogui_win.py @@ -1196,15 +1194,18 @@ def main(): # Call to QApplication outside the try-except so we can show error messages app = QApplication(sys.argv) try: # noqa: PLW0717 # We really want to catch everything here - if sys.platform == "win32": - myappid = f"Toufool.AutoSplit.v{AUTOSPLIT_VERSION}" - shell32.SetCurrentProcessExplicitAppUserModelID(myappid) - # Decouple from the executable basename (which varies per build) app.setApplicationName("AutoSplit") app.setApplicationVersion(AUTOSPLIT_VERSION) app.setWindowIcon(QtGui.QIcon(":/resources/icon.ico")) + if sys.platform == "win32": + # Technically not needed since we version the filename now, + # but kept in case users strips down the executable filename + set_aumid = ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID # pyright: ignore[reportAttributeAccessIssue] + set_aumid.restype = ctypes.HRESULT # auto-raises OSError on failure + set_aumid(f"Toufool.AutoSplit.v{AUTOSPLIT_VERSION}") + if is_already_open(): error_messages.already_open() if KEYBOARD_GROUPS_ISSUE: diff --git a/src/error_messages.py b/src/error_messages.py index e318e286..21a15df3 100644 --- a/src/error_messages.py +++ b/src/error_messages.py @@ -287,7 +287,7 @@ def excepthook( " returned a result with an error set" ): return - # Whithin LiveSplit excepthook needs to use MainWindow's signals to show errors + # Within LiveSplit excepthook needs to use MainWindow's signals to show errors autosplit.show_error_signal.emit(lambda: exception_traceback(exception)) return excepthook From 3cee14c12097bb2198334b6d9a043538f4e75a7c Mon Sep 17 00:00:00 2001 From: Avasam Date: Sun, 12 Jul 2026 01:25:45 -0400 Subject: [PATCH 04/10] Try removing --upx-exclude=win32*.pyd --- scripts/build.ps1 | 3 +-- src/AutoSplit.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/scripts/build.ps1 b/scripts/build.ps1 index 74c6fb62..6d8cf17a 100644 --- a/scripts/build.ps1 +++ b/scripts/build.ps1 @@ -45,8 +45,7 @@ try { # UPX self-decompression breaks under Wine ("DLL initialisation failed"). # Native Windows tolerates it, Wine's loader doesn't. Exclude them from compression. '--upx-exclude=pythoncom*.dll', - '--upx-exclude=pywintypes*.dll', - '--upx-exclude=win32*.pyd') + '--upx-exclude=pywintypes*.dll') } else { # Missing upx executable should be enough, but let's be explicit diff --git a/src/AutoSplit.py b/src/AutoSplit.py index 42978ef1..ec06596f 100755 --- a/src/AutoSplit.py +++ b/src/AutoSplit.py @@ -1202,7 +1202,7 @@ def main(): if sys.platform == "win32": # Technically not needed since we version the filename now, # but kept in case users strips down the executable filename - set_aumid = ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID # pyright: ignore[reportAttributeAccessIssue] + set_aumid = ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID set_aumid.restype = ctypes.HRESULT # auto-raises OSError on failure set_aumid(f"Toufool.AutoSplit.v{AUTOSPLIT_VERSION}") From 54c2f31a7be20010b605c85da3f950e44a651f43 Mon Sep 17 00:00:00 2001 From: Avasam Date: Sun, 12 Jul 2026 02:06:27 -0400 Subject: [PATCH 05/10] Move down `import win32api` in special import blocks --- src/capture_method/DesktopDuplicationCaptureMethod.py | 9 ++++++--- src/capture_method/WindowsGraphicsCaptureMethod.py | 7 ++++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/capture_method/DesktopDuplicationCaptureMethod.py b/src/capture_method/DesktopDuplicationCaptureMethod.py index 874b5a16..a855f11a 100644 --- a/src/capture_method/DesktopDuplicationCaptureMethod.py +++ b/src/capture_method/DesktopDuplicationCaptureMethod.py @@ -10,7 +10,6 @@ import cv2 import d3dshot -import win32api import win32con import win32gui @@ -21,9 +20,13 @@ from AutoSplit import AutoSplit -try: # Test for laptop cross-GPU Desktop Duplication issue +try: + # Test for laptop cross-GPU Desktop Duplication issue (ModuleNotFoundError or COMError) d3dshot.create(capture_output="numpy") -except ModuleNotFoundError, COMError: + # Throws ImportError in Wine+UPX: win32api.pyd imports RegOpenKeyTransactedW (absent from + # Wine's advapi32); UPX's load-time GetProcAddress import rebuild then fails DLL init. + import win32api +except ModuleNotFoundError, COMError, ImportError: IS_DESKTOP_DUPLICATION_SUPPORTED = False # pyright: ignore[reportConstantRedefinition] else: IS_DESKTOP_DUPLICATION_SUPPORTED = True diff --git a/src/capture_method/WindowsGraphicsCaptureMethod.py b/src/capture_method/WindowsGraphicsCaptureMethod.py index afb947d9..6020ab8d 100644 --- a/src/capture_method/WindowsGraphicsCaptureMethod.py +++ b/src/capture_method/WindowsGraphicsCaptureMethod.py @@ -9,7 +9,6 @@ import cv2 import numpy as np -import win32api import win32gui import winerror from winrt.windows.graphics.capture import Direct3D11CaptureFramePool, GraphicsCaptureSession @@ -31,6 +30,10 @@ WGC_NO_BORDER_MIN_BUILD = 20348 try: + # Throws ImportError in Wine+UPX: win32api.pyd imports RegOpenKeyTransactedW (absent from + # Wine's advapi32); UPX's load-time GetProcAddress import rebuild then fails DLL init. + import win32api + # Wine hasn't implemented CreateDirect3D11DeviceFromDXGIDevice yet # https://bugs.winehq.org/show_bug.cgi?id=52487 # Keep this check for a while even after it's implemented @@ -41,6 +44,8 @@ "CreateDirect3D11DeviceFromDXGIDevice", # pyright: ignore[reportArgumentType] ) ) +except ImportError: + IS_WGC_SUPPORTED = False # pyright: ignore[reportConstantRedefinition] except win32api.error as exception: if exception.winerror != winerror.ERROR_PROC_NOT_FOUND: raise From 04076203a0606d7d51080d3db27d1ba1395d35a5 Mon Sep 17 00:00:00 2001 From: Avasam Date: Sun, 12 Jul 2026 02:34:13 -0400 Subject: [PATCH 06/10] Remove fixed wine bug from list --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 968d7b70..553fa6b4 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,6 @@ Not a developer? You can still help through the following methods: - Sharing AutoSplit with other speedrunners - Starring the repository Example - Upvoting 👍 the following upstream issues in libraries and tools we use: - - - - - From 7d028d16a3b7b3d3f05beeaac65edb162db561ba Mon Sep 17 00:00:00 2001 From: Avasam Date: Sun, 12 Jul 2026 02:49:08 -0400 Subject: [PATCH 07/10] --upx-exclude=win32api.pyd --- scripts/build.ps1 | 4 +++- src/capture_method/DesktopDuplicationCaptureMethod.py | 4 ++-- src/capture_method/WindowsGraphicsCaptureMethod.py | 7 +------ 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/scripts/build.ps1 b/scripts/build.ps1 index 6d8cf17a..853ee459 100644 --- a/scripts/build.ps1 +++ b/scripts/build.ps1 @@ -45,7 +45,9 @@ try { # UPX self-decompression breaks under Wine ("DLL initialisation failed"). # Native Windows tolerates it, Wine's loader doesn't. Exclude them from compression. '--upx-exclude=pythoncom*.dll', - '--upx-exclude=pywintypes*.dll') + '--upx-exclude=pywintypes*.dll', + # Wine doesn't even stub `ADVAPI32.RegOpenKeyTransactedW`/`ADVAPI32.RegDeleteKeyTransactedW` + '--upx-exclude=win32api.pyd') } else { # Missing upx executable should be enough, but let's be explicit diff --git a/src/capture_method/DesktopDuplicationCaptureMethod.py b/src/capture_method/DesktopDuplicationCaptureMethod.py index a855f11a..980e0cca 100644 --- a/src/capture_method/DesktopDuplicationCaptureMethod.py +++ b/src/capture_method/DesktopDuplicationCaptureMethod.py @@ -10,6 +10,7 @@ import cv2 import d3dshot +import win32api import win32con import win32gui @@ -25,8 +26,7 @@ d3dshot.create(capture_output="numpy") # Throws ImportError in Wine+UPX: win32api.pyd imports RegOpenKeyTransactedW (absent from # Wine's advapi32); UPX's load-time GetProcAddress import rebuild then fails DLL init. - import win32api -except ModuleNotFoundError, COMError, ImportError: +except ModuleNotFoundError, COMError: IS_DESKTOP_DUPLICATION_SUPPORTED = False # pyright: ignore[reportConstantRedefinition] else: IS_DESKTOP_DUPLICATION_SUPPORTED = True diff --git a/src/capture_method/WindowsGraphicsCaptureMethod.py b/src/capture_method/WindowsGraphicsCaptureMethod.py index 6020ab8d..afb947d9 100644 --- a/src/capture_method/WindowsGraphicsCaptureMethod.py +++ b/src/capture_method/WindowsGraphicsCaptureMethod.py @@ -9,6 +9,7 @@ import cv2 import numpy as np +import win32api import win32gui import winerror from winrt.windows.graphics.capture import Direct3D11CaptureFramePool, GraphicsCaptureSession @@ -30,10 +31,6 @@ WGC_NO_BORDER_MIN_BUILD = 20348 try: - # Throws ImportError in Wine+UPX: win32api.pyd imports RegOpenKeyTransactedW (absent from - # Wine's advapi32); UPX's load-time GetProcAddress import rebuild then fails DLL init. - import win32api - # Wine hasn't implemented CreateDirect3D11DeviceFromDXGIDevice yet # https://bugs.winehq.org/show_bug.cgi?id=52487 # Keep this check for a while even after it's implemented @@ -44,8 +41,6 @@ "CreateDirect3D11DeviceFromDXGIDevice", # pyright: ignore[reportArgumentType] ) ) -except ImportError: - IS_WGC_SUPPORTED = False # pyright: ignore[reportConstantRedefinition] except win32api.error as exception: if exception.winerror != winerror.ERROR_PROC_NOT_FOUND: raise From f599e10143cbed14fa5e9ca8275c57426884b39f Mon Sep 17 00:00:00 2001 From: Avasam Date: Sun, 12 Jul 2026 03:07:10 -0400 Subject: [PATCH 08/10] Try w/o --upx-exclude=pywintypes*.dll --- scripts/build.ps1 | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/scripts/build.ps1 b/scripts/build.ps1 index 853ee459..7b53e9a4 100644 --- a/scripts/build.ps1 +++ b/scripts/build.ps1 @@ -41,12 +41,9 @@ try { if (-not $WineCompat -and -not $IsLinux) { $arguments += '--upx-dir=scripts/.upx' $arguments += @( - # pywin32's DLLs do custom load-time magic (__import_pywin32_system_module__) that - # UPX self-decompression breaks under Wine ("DLL initialisation failed"). - # Native Windows tolerates it, Wine's loader doesn't. Exclude them from compression. + # Wine doesn't export (not even stub) win32api ole32.Co{Get,Set}CancelObject '--upx-exclude=pythoncom*.dll', - '--upx-exclude=pywintypes*.dll', - # Wine doesn't even stub `ADVAPI32.RegOpenKeyTransactedW`/`ADVAPI32.RegDeleteKeyTransactedW` + # Wine doesn't export (not even stub) `ADVAPI32.Reg{Open,Delete}KeyTransactedW` '--upx-exclude=win32api.pyd') } else { From fe36a562d6cf0bf464c50a07dc8c7753f0a7a219 Mon Sep 17 00:00:00 2001 From: Avasam Date: Sun, 12 Jul 2026 03:21:49 -0400 Subject: [PATCH 09/10] better comment --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 553fa6b4..c8e58e54 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ Linux users, note that LiveSplit Desktop, with additional components, is only av - Only the BitBlt Capture method is supported. Wine [does not support `CreateDirect3D11DeviceFromDXGIDevice`](https://bugs.winehq.org/show_bug.cgi?id=52487) - No Video Capture Device (ie Webcam, OBS Virtual Cam). Wine [does not support DirectShow Device Enumeration](https://gitlab.winehq.org/wine/wine/-/wikis/Hardware#restrictions:~:text=camera) - Requires Wine 10.1+ / Steam Proton 11+ (due to [added `crealf` implementation](https://gitlab.winehq.org/wine/wine/-/releases/wine-10.1#:~:text=crealf)) -- Wine 10.1 to 11.2 must use the `WineCompat` version of the Windows build (same build but without UPX compression) as Wine hadn't [implemented `PssQuerySnapshot`](https://gitlab.winehq.org/wine/wine/-/merge_requests/8779) yet. +- Wine 10.1 to 11.2 must use the `WineCompat` version of the Windows build (same build but without UPX compression) as Wine hadn't [stubbed `PssQuerySnapshot`](https://gitlab.winehq.org/wine/wine/-/merge_requests/8779) yet. - Wine 11.3+ can use the regular Windows build. - Only applications running within the **same wineserver instance** can be recorded. Which means that if you want to record a Steam Game for example, you would need to run AutoSplit through the same Proton version as the target game, targetting the game's Wine prefix. - For steam games, this can be made a lot easier using [`protontricks`](https://protontricks.com/): `protontricks-launch --appid ` From 7b5e03c8cf25bd79395f88064d260ecff5c3da3a Mon Sep 17 00:00:00 2001 From: Avasam Date: Sun, 12 Jul 2026 03:30:12 -0400 Subject: [PATCH 10/10] Update src/capture_method/DesktopDuplicationCaptureMethod.py --- src/capture_method/DesktopDuplicationCaptureMethod.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/capture_method/DesktopDuplicationCaptureMethod.py b/src/capture_method/DesktopDuplicationCaptureMethod.py index 980e0cca..25316de4 100644 --- a/src/capture_method/DesktopDuplicationCaptureMethod.py +++ b/src/capture_method/DesktopDuplicationCaptureMethod.py @@ -24,8 +24,6 @@ try: # Test for laptop cross-GPU Desktop Duplication issue (ModuleNotFoundError or COMError) d3dshot.create(capture_output="numpy") - # Throws ImportError in Wine+UPX: win32api.pyd imports RegOpenKeyTransactedW (absent from - # Wine's advapi32); UPX's load-time GetProcAddress import rebuild then fails DLL init. except ModuleNotFoundError, COMError: IS_DESKTOP_DUPLICATION_SUPPORTED = False # pyright: ignore[reportConstantRedefinition] else: