diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d99b51e1e9..227038f5cb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -850,6 +850,189 @@ jobs: path: build/bundles retention-days: 5 + windows-appx: + name: Windows Store + needs: + - source + - windows + + if: needs.source.outputs.is_tag == 'true' + runs-on: windows-latest + + steps: + - name: Download source + uses: actions/download-artifact@v2 + with: + name: internal-source + + - name: Unpack source + shell: bash + run: | + tar -xf source.tar.gz --strip-components=1 + + - name: Download x86 build + uses: actions/download-artifact@v2 + with: + name: openttd-windows-x86 + + - name: Download x64 build + uses: actions/download-artifact@v2 + with: + name: openttd-windows-x64 + + - name: Download arm64 build + uses: actions/download-artifact@v2 + with: + name: openttd-windows-arm64 + + - name: Unpack builds + shell: bash + run: | + mkdir builds + cd builds + + function extract { + mkdir $1 + + # Extract the zip version of the release + unzip ../openttd-*-windows-$2.zip -d $1 + + # Remove the extraneous directory + mv $1/openttd-*-windows-$2/* $1/ + rmdir $1/openttd-*-windows-$2 + + # Move the openttd.exe to the '{arch}-binaries' folder + mkdir $1-binaries + mv $1/openttd.exe $1-binaries/ + } + + extract x86 win32 + extract x64 win64 + extract arm64 arm64 + + # Use the "x86" folder as the source of the common binaries (lang files, etc) and remove the others + mv x86 common-binaries + rm -rf x64 arm64 + + - name: Install OpenGFX + shell: bash + run: | + mkdir -p builds/common-binaries/baseset + cd builds/common-binaries/baseset + + echo "::group::Download OpenGFX" + curl -L https://cdn.openttd.org/opengfx-releases/7.1/opengfx-7.1-all.zip -o opengfx-all.zip + echo "::endgroup::" + + echo "::group::Unpack OpenGFX" + unzip opengfx-all.zip + tar xf opengfx-*.tar + echo "::endgroup::" + + rm -f opengfx-all.zip opengfx-*.tar + + - name: Install OpenMSX + shell: bash + run: | + mkdir -p builds/common-binaries/baseset + cd builds/common-binaries/baseset + + echo "::group::Download OpenMSX" + curl -L https://cdn.openttd.org/openmsx-releases/0.4.2/openmsx-0.4.2-all.zip -o openmsx-all.zip + echo "::endgroup::" + + echo "::group::Unpack OpenGFX" + unzip openmsx-all.zip + tar xf openmsx-*.tar + echo "::endgroup::" + + rm -f openmsx-all.zip openmsx-*.tar + + - name: Install OpenSFX + shell: bash + run: | + mkdir -p builds/common-binaries/baseset/opensfx + cd builds/common-binaries/baseset/opensfx + + echo "::group::Download OpenSFX" + curl -L https://cdn.openttd.org/opensfx-releases/1.0.3/opensfx-1.0.3-all.zip -o opensfx-all.zip + echo "::endgroup::" + + echo "::group::Unpack OpenSFX" + unzip opensfx-all.zip + tar xf opensfx-*.tar + echo "::endgroup::" + + rm -f opensfx-all.zip opensfx-*.tar + + - name: Generate signing certificate + shell: cmd + run: | + cd builds + + REM We need to provide a signed .appx to the Windows Store, so generate a certificate with password 'password' + call ..\os\windows\winstore\generate-key.bat "CN=78024DA8-4BE4-4C77-B12E-547BBF7359D2" password cert.pfx + + - name: Generate assets + shell: cmd + run: | + cd os\windows\winstore + call generate-assets.bat + + - name: Prepare manifests + shell: cmd + run: | + cd builds + mkdir manifests + + REM Set the version environment variable + call ..\os\windows\winstore\set-version.bat x86-binaries\openttd.exe + + call ..\os\windows\winstore\prepare-manifests.bat manifests "CN=78024DA8-4BE4-4C77-B12E-547BBF7359D2" "57420OpenTTDDevelopers.OpenTTDofficial" + + - name: Prepare binaries + shell: bash + run: | + cd builds + + # Copy the Windows Store assets + mkdir common-binaries/Assets + cp -R ../os/windows/winstore/assets-common/* common-binaries/Assets/ + + mkdir Assets + cp -R ../os/windows/winstore/assets/* Assets/ + + cp manifests/*.xml . + + - name: Build + shell: cmd + run: | + REM Add the Windows SDK tools to the PATH + + echo|set /p="SET VS_INSTALLDIR=" > _vspath.bat + vswhere -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath >> _vspath.bat + call _vspath.bat + call "%VS_INSTALLDIR%\Common7\Tools\VsDevCmd.bat" + + REM Set the version environment variable + call os\windows\winstore\set-version.bat builds\x86-binaries\openttd.exe + + cd builds + mkdir output + + REM Build and sign the package + makeappx build /v /f PackagingLayout.xml /op output\ /bv %OTTD_VERSION% /pv %OTTD_VERSION% /ca + SignTool sign /fd sha256 /a /f cert.pfx /p password "output\OpenTTD.appxbundle" + + - name: Store appx + uses: actions/upload-artifact@v2 + with: + name: openttd-windows-store + path: | + builds/output/OpenTTD.appxbundle + builds/cert.pfx + retention-days: 5 + upload: name: Upload (AWS) needs: diff --git a/os/windows/winstore/generate-assets.bat b/os/windows/winstore/generate-assets.bat new file mode 100644 index 0000000000..387fd57b85 --- /dev/null +++ b/os/windows/winstore/generate-assets.bat @@ -0,0 +1,2 @@ +@echo off +powershell -File "%~dp0generate-assets.ps1" diff --git a/os/windows/winstore/generate-assets.ps1 b/os/windows/winstore/generate-assets.ps1 new file mode 100644 index 0000000000..89c48e6ecf --- /dev/null +++ b/os/windows/winstore/generate-assets.ps1 @@ -0,0 +1,48 @@ +function ResizeImage() { + param([String]$sourcePath, [Int]$targetWidth, [Int]$targetHeight, [String]$targetPath) + + Add-Type -AssemblyName "System.Drawing" + + $img = [System.Drawing.Image]::FromFile($sourcePath) + + $ratioX = $targetWidth / $img.Width; + $ratioY = $targetHeight / $img.Height; + + $ratio = $ratioY + + if ($ratioX -le $ratioY) { + $ratio = $ratioX + } + + $newWidth = [int] ($img.Width * $ratio) + $newHeight = [int] ($img.Height * $ratio) + + $resizedImage = New-Object System.Drawing.Bitmap($targetWidth, $targetHeight) + $graph = [System.Drawing.Graphics]::FromImage($resizedImage) + $graph.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic + + $graph.Clear([System.Drawing.Color]::Transparent) + $graph.DrawImage($img, $targetWidth / 2 - $newWidth / 2, $targetHeight / 2 - $newHeight / 2, $newWidth, $newHeight) + + $resizedImage.Save($targetPath) + $resizedImage.Dispose() + $img.Dispose() +} + +$logoPath = "..\..\..\media\openttd.2048.png" + +# Create the main image assets required for the Windows Store +New-Item -Path "." -Name "assets" -ItemType "directory" -Force +ResizeImage $logoPath 1240 1240 "assets\LargeTile.png" +ResizeImage $logoPath 284 284 "assets\SmallTile.png" +ResizeImage $logoPath 2480 1200 "assets\SplashScreen.png" +ResizeImage $logoPath 176 176 "assets\Square44x44Logo.png" +Copy-Item "assets\Square44x44Logo.png" -Destination "assets\Square44x44Logo.targetsize-44_altform-unplated.png" +ResizeImage $logoPath 600 600 "assets\Square150x150Logo.png" +Copy-Item "assets\Square150x150Logo.png" -Destination "assets\Square150x150Logo.targetsize-150_altform-unplated.png" +ResizeImage $logoPath 200 200 "assets\StoreLogo.png" +ResizeImage $logoPath 1240 600 "assets\Wide310x150Logo.png" + +# Copy the logo for the store for the common package +New-Item -Path "." -Name "assets-common" -ItemType "directory" -Force +Copy-Item "assets\StoreLogo.png" -Destination "assets-common\StoreLogo.png" diff --git a/os/windows/winstore/generate-key.bat b/os/windows/winstore/generate-key.bat new file mode 100644 index 0000000000..859d595d9c --- /dev/null +++ b/os/windows/winstore/generate-key.bat @@ -0,0 +1,2 @@ +@echo off +powershell -File "%~dp0generate-key.ps1" %1 %2 %3 diff --git a/os/windows/winstore/generate-key.ps1 b/os/windows/winstore/generate-key.ps1 new file mode 100644 index 0000000000..f59eb038e4 --- /dev/null +++ b/os/windows/winstore/generate-key.ps1 @@ -0,0 +1,21 @@ +[CmdletBinding()] +[Alias()] +Param +( + # Publisher ("CN=xyz") + [Parameter(Mandatory=$true, Position=0)] + $Publisher, + + # Password + [Parameter(Mandatory=$true, Position=1)] + $PasswordParam, + + # Filename + [Parameter(Mandatory=$true, Position=2)] + $OutputFilename +) + +$cert = New-SelfSignedCertificate -Type Custom -Subject $Publisher -KeyUsage DigitalSignature -FriendlyName "OpenTTD signing certificate" -CertStoreLocation "Cert:\CurrentUser\My" -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.3", "2.5.29.19={text}") + +$password = ConvertTo-SecureString -String $PasswordParam -Force -AsPlainText +Export-PfxCertificate -cert "Cert:\CurrentUser\My\$($cert.Thumbprint)" -FilePath $OutputFilename -Password $password diff --git a/os/windows/winstore/manifests/AssetsPackage.appxmanifest b/os/windows/winstore/manifests/AssetsPackage.appxmanifest new file mode 100644 index 0000000000..a0e8f29eda --- /dev/null +++ b/os/windows/winstore/manifests/AssetsPackage.appxmanifest @@ -0,0 +1,68 @@ + + + + + false + OpenTTD (official) + OpenTTD Developers + Assets\StoreLogoCommon.png + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/os/windows/winstore/manifests/Package.appxmanifest b/os/windows/winstore/manifests/Package.appxmanifest new file mode 100644 index 0000000000..7eb4a5c2b7 --- /dev/null +++ b/os/windows/winstore/manifests/Package.appxmanifest @@ -0,0 +1,83 @@ + + + + + OpenTTD (official) + OpenTTD Developers + Assets\StoreLogo.png + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/os/windows/winstore/manifests/PackagingLayout.xml b/os/windows/winstore/manifests/PackagingLayout.xml new file mode 100644 index 0000000000..dc16e45fa8 --- /dev/null +++ b/os/windows/winstore/manifests/PackagingLayout.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/os/windows/winstore/prepare-manifests.bat b/os/windows/winstore/prepare-manifests.bat new file mode 100644 index 0000000000..634b51e5ff --- /dev/null +++ b/os/windows/winstore/prepare-manifests.bat @@ -0,0 +1,2 @@ +@echo off +powershell -File "%~dp0prepare-manifests.ps1" %1 %2 %3 %OTTD_VERSION% diff --git a/os/windows/winstore/prepare-manifests.ps1 b/os/windows/winstore/prepare-manifests.ps1 new file mode 100644 index 0000000000..4bd1f4cb2f --- /dev/null +++ b/os/windows/winstore/prepare-manifests.ps1 @@ -0,0 +1,42 @@ +[CmdletBinding()] +[Alias()] +Param +( + # Output folder + [Parameter(Mandatory=$true, Position=0)] + $OutputFolder, + + # Publisher ("CN=xyz") + [Parameter(Mandatory=$true, Position=1)] + $Publisher, + + # IdentityName + [Parameter(Mandatory=$true, Position=2)] + $IdentityName, + + # Version + [Parameter(Mandatory=$true, Position=3)] + $AppVersion +) + +function Prepare-Manifest { + param ( + $Architecture + ) + + (Get-Content "$($PSScriptRoot)\manifests\Package.appxmanifest").replace('$PUBLISHER$', $Publisher).replace('$IDENTITY_NAME$', $IdentityName).replace('$VERSION$', $AppVersion).replace('$ARCHITECTURE$', $Architecture) | Set-Content "$($OutputFolder)\Package-$($Architecture).appxmanifest" +} + +# Prepare the application binary manifests +Prepare-Manifest x86 +Prepare-Manifest x64 +Prepare-Manifest arm64 + +# Prepare the assets package manifest +(Get-Content "$($PSScriptRoot)\manifests\AssetsPackage.appxmanifest").replace('$PUBLISHER$', $Publisher).replace('$IDENTITY_NAME$', $IdentityName).replace('$VERSION$', $AppVersion) | Set-Content "$($OutputFolder)\AssetsPackage.appxmanifest" + +# Prepare the overall package manifest +(Get-Content "$($PSScriptRoot)\manifests\Package.appxmanifest").replace('$PUBLISHER$', $Publisher).replace('$IDENTITY_NAME$', $IdentityName).replace('$VERSION$', $AppVersion).replace(' ProcessorArchitecture="$ARCHITECTURE$"', '') | Set-Content "$($OutputFolder)\Package.appxmanifest" + +# Copy the PackagingLayout XML file +(Get-Content "$($PSScriptRoot)\manifests\PackagingLayout.xml") | Set-Content "$($OutputFolder)\PackagingLayout.xml" diff --git a/os/windows/winstore/set-version.bat b/os/windows/winstore/set-version.bat new file mode 100644 index 0000000000..f198661787 --- /dev/null +++ b/os/windows/winstore/set-version.bat @@ -0,0 +1,14 @@ +@echo off +if [%1]==[] goto err + +powershell -File "%~dp0set-version.ps1" %1 > "%temp%\ottd-set-version.bat" +if not errorlevel 0 goto err +call "%temp%\ottd-set-version.bat" +del /q "%temp%\ottd-set-version.bat" + +@rem Version number will now be in %OTTD_VERSION% + +goto :eof + +:err +echo Please supply the path of openttd.exe as the argument to this batch file. diff --git a/os/windows/winstore/set-version.ps1 b/os/windows/winstore/set-version.ps1 new file mode 100644 index 0000000000..ba048581e2 --- /dev/null +++ b/os/windows/winstore/set-version.ps1 @@ -0,0 +1,23 @@ +[CmdletBinding()] +[Alias()] +Param +( + # EXE path + [Parameter(Mandatory=$true, Position=0)] + $ExePath +) + +try +{ + $versionInfo = (Get-Item "$ExePath").VersionInfo + + # Generate the app version - the build number (MS calls it revision) is always 0 because the Windows Store requires that + $AppVersion = "$($versionInfo.FileMajorPart).$($versionInfo.FileMinorPart).$($versionInfo.FileBuildPart).0" + + Write-Output "SET OTTD_VERSION=$($AppVersion)" +} +catch +{ + Write-Output "@ECHO Error retrieving EXE version - did you provide a path?" + exit 1 +}