├── README.md ├── LICENSE └── godot-appx-repackager.ps1 /README.md: -------------------------------------------------------------------------------- 1 | # godot-appx-repackager 2 | Powershell script to correctly repackage broken APPX files generated by Godot 3.5 3 | 4 | # Usage 5 | ``` 6 | .\godot-appx-repackager.ps1 game.appx 7 | ``` 8 | # Tips 9 | - X64 only! 10 | - UWP export fields must be 4 characters long at least. 11 | - publisherName must match with the one provided in the Godot UWP export field (CN=RAWRLAB). 12 | - A self-signed PFX certificate will be generated if you don't provide one. 13 | - Avoid spaces and special characters in any paths, just in case. 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 panreyes 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /godot-appx-repackager.ps1: -------------------------------------------------------------------------------- 1 | # godot-appx-repackager: Powershell script to correctly repackage broken APPX files generated by Godot 3.5. 2 | # · Developed by Pablo Navarro, from RAWRLAB Games. 2023 3 | # · License: MIT. But feel free to do as you please with this! 4 | # · Usage: .\godot-appx-repackager.ps1 game.appx 5 | # · Tips: 6 | # - X64 only! 7 | # - UWP export fields must be 4 characters long at least. 8 | # - publisherName must match with the one provided in the Godot UWP export field (CN=RAWRLAB). 9 | # - A self-signed PFX certificate will be generated if you don't provide one. 10 | # - Avoid spaces and special characters in any paths, just in case. 11 | # ---------------------------------- 12 | 13 | # Configuration 14 | $certFilePFX = "" 15 | $certPass = "amazingPassword" 16 | $publisherName = "RAWRLAB" 17 | $mainFolder = $env:TEMP + "\appx-repack" 18 | $appxFileName = "" 19 | 20 | # ---------------------------- 21 | # Other variables 22 | $buildToolsURL = "https://globalcdn.nuget.org/packages/microsoft.windows.sdk.buildtools.10.0.22621.756.nupkg" 23 | $angleURL = "https://globalcdn.nuget.org/packages/angle.windowsstore.2.1.13.nupkg" 24 | 25 | $gameExtractionFolder = $mainFolder + "\game" 26 | $toolsExtractionFolder = $mainFolder + "\tools" 27 | 28 | $toolsFolder = $toolsExtractionFolder + "\bin\10.0.22621.0\x64" 29 | $makeappxPath = $toolsFolder + "\makeappx.exe" 30 | $makecertPath = $toolsFolder + "\makecert.exe" 31 | $pvk2pfxPath = $toolsFolder + "\pvk2pfx.exe" 32 | $signtoolPath = $toolsFolder + "\signtool.exe" 33 | 34 | $angleFolder = $toolsExtractionFolder + "\bin\UAP\x64" 35 | $libEGLPath = $angleFolder + "\libEGL.dll" 36 | $libGLESPath = $angleFolder + "\libGLESv2.dll" 37 | 38 | # ------------------------ 39 | 40 | # If a certificate isn't configured, just generate one 41 | if(!$certFilePFX) { 42 | $certFilePFX = $mainFolder + "\MyKey.pfx" 43 | } 44 | 45 | # Check if the script was called with something as $args[0], luckily an APPX path 46 | if (!$appxFileName) { 47 | if ($args.Count -eq 1) { 48 | $appxFileName = $args[0] 49 | } else { 50 | Write-Output "Please provide an APPX as a command-line argument." 51 | return 52 | } 53 | } 54 | 55 | # Check if APPX file exists 56 | if (!(Test-Path -Path $appxFileName)) { 57 | Write-Output "Provided APPX file does not exist." 58 | return 59 | } 60 | 61 | # Create directories if they don't exit 62 | New-Item -ItemType Directory -Path $toolsExtractionFolder -Force | Out-Null 63 | New-Item -ItemType Directory -Path $gameExtractionFolder -Force | Out-Null 64 | 65 | # If libEGL.dll does not exist, download Angle DLLs 66 | if (!(Test-Path -Path $libEGLPath)) { 67 | $tempZipFile = $env:TEMP + "\temp.zip" 68 | Invoke-WebRequest -Uri $angleURL -OutFile $tempZipFile 69 | Expand-Archive -Path $tempZipFile -DestinationPath $toolsExtractionFolder -Force 70 | Remove-Item $tempZipFile 71 | } 72 | 73 | if (!(Test-Path -Path $libEGLPath)) { 74 | Write-Output "Could not download or extract the Angle DLLs." 75 | return 76 | } 77 | 78 | # If makeappx.exe does not exist, download Windows build tools 79 | if (!(Test-Path -Path $makeappxPath)) { 80 | $tempZipFile = $env:TEMP + "\temp.zip" 81 | Invoke-WebRequest -Uri $buildToolsURL -OutFile $tempZipFile 82 | Expand-Archive -Path $tempZipFile -DestinationPath $toolsExtractionFolder -Force 83 | Remove-Item $tempZipFile 84 | } 85 | 86 | if (!(Test-Path -Path $makeappxPath)) { 87 | Write-Output "Could not download or extract the Windows build tools." 88 | return 89 | } 90 | 91 | # If cert file does not exist, generate one 92 | if (!(Test-Path -Path $certFilePFX)) { 93 | $securePassword = ConvertTo-SecureString -String $certPass -AsPlainText -Force 94 | $newCert = New-SelfSignedCertificate -CertStoreLocation Cert:\CurrentUser\My -Subject ('CN=' + $publisherName) -HashAlgorithm 'SHA256' -TextExtension @( "2.5.29.37={text}1.3.6.1.5.5.7.3.3,1.3.6.1.4.1.311.84.3.1", "2.5.29.19={text}false") 95 | Export-PfxCertificate -FilePath $certFilePFX -Password $securePassword -Cert $newCert 96 | } 97 | 98 | if (!(Test-Path -Path $certFilePFX)) { 99 | Write-Output "Error: Could not generate a test certificate." 100 | return 101 | } 102 | 103 | # Extract broken APPX file and delete it 104 | Rename-Item -Path $appxFileName -NewName ($appxFileName + ".zip") -Force 105 | Expand-Archive -Path ($appxFileName + ".zip") -DestinationPath $gameExtractionFolder -Force 106 | 107 | # Copy the Angle DLLs 108 | Copy-Item -Path $libEGLPath -Destination $gameExtractionFolder -Force 109 | Copy-Item -Path $libGLESPath -Destination $gameExtractionFolder -Force 110 | 111 | # Repackage it with makeappx 112 | & $makeappxPath pack /d $gameExtractionFolder /p $appxFileName 113 | 114 | if (!(Test-Path -Path $appxFileName)) { 115 | Rename-Item -Path ($appxFileName + ".zip") -NewName $appxFileName -Force 116 | Write-Output "Error: Could not repackage the APPX file." 117 | return 118 | } 119 | 120 | # Delete the extracted game folder and the old APPX 121 | Remove-Item -Path ($appxFileName + ".zip") -Force 122 | Remove-Item -Recurse -Path $gameExtractionFolder -Force 123 | 124 | # Sign it with signtool 125 | & $signtoolPath sign /fd SHA256 /a /f $certFilePFX /p $certPass $appxFileName 126 | 127 | if (!$?) { 128 | Write-Output "Error: Could not sign the APPX file." 129 | return 130 | } else { 131 | Write-Output "Process completed succesfully!" 132 | return 133 | } --------------------------------------------------------------------------------