diff --git a/Makefile b/Makefile index a00c4caedd..5a5ded0a60 100644 --- a/Makefile +++ b/Makefile @@ -76,9 +76,6 @@ INSTALL_DATA = $(INSTALL) -m644 # Toolchain MSBUILD = msbuild -verbosity:m -nologo -# Enable 32 bit builds while generating the windows installer -WIN32 = false - # dependencies ifndef TARGETPLATFORM UNAME_S := $(shell uname -s) diff --git a/OpenRA.WindowsLauncher/App.config b/OpenRA.WindowsLauncher/App.config new file mode 100644 index 0000000000..cab8f010ca --- /dev/null +++ b/OpenRA.WindowsLauncher/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/OpenRA.WindowsLauncher/OpenRA.WindowsLauncher.csproj b/OpenRA.WindowsLauncher/OpenRA.WindowsLauncher.csproj new file mode 100644 index 0000000000..79233e8625 --- /dev/null +++ b/OpenRA.WindowsLauncher/OpenRA.WindowsLauncher.csproj @@ -0,0 +1,61 @@ + + + winexe + net472 + true + true + false + 7.3 + true + true + false + ../bin + false + AnyCPU + false + false + ..\OpenRA.ruleset + Release;Debug + $(LauncherName) + $(LauncherIcon) + + + + + + + DEBUG;TRACE + false + + + true + + + + + + <_Parameter1>ModID + <_Parameter2>$(ModID) + + + <_Parameter1>DisplayName + <_Parameter2>$(DisplayName) + + + <_Parameter1>FaqUrl + <_Parameter2>$(FaqUrl) + + + + + + + + + + + + + + + diff --git a/OpenRA.WindowsLauncher/Program.cs b/OpenRA.WindowsLauncher/Program.cs new file mode 100644 index 0000000000..ae1a98a144 --- /dev/null +++ b/OpenRA.WindowsLauncher/Program.cs @@ -0,0 +1,197 @@ +#region Copyright & License Information +/* + * Copyright 2007-2020 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; +using SDL2; + +namespace OpenRA.WindowsLauncher +{ + class WindowsLauncher + { + [DllImport("user32.dll")] + static extern bool SetForegroundWindow(IntPtr hWnd); + + [DllImport("user32.dll")] + static extern bool AllowSetForegroundWindow(int dwProcessId); + + static Process gameProcess; + static string modID; + static string displayName; + static string faqUrl; + + static int Main(string[] args) + { + // The modID, displayName, and faqUrl variables are embedded in the assembly metadata by defining + // -p:ModID="mymod", -p:DisplayName="My Mod", -p:FaqUrl="https://my.tld/faq" when compiling the project + var attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(); + foreach (var a in attributes) + { + if (a is AssemblyMetadataAttribute metadata) + { + switch (metadata.Key) + { + case "ModID": modID = metadata.Value; break; + case "DisplayName": displayName = metadata.Value; break; + case "FaqUrl": faqUrl = metadata.Value; break; + } + } + } + + if (args.Any(x => x.StartsWith("Engine.LaunchPath=", StringComparison.Ordinal))) + return RunGame(args); + + return RunInnerLauncher(args); + } + + static int RunGame(string[] args) + { + var launcherPath = Assembly.GetExecutingAssembly().Location; + var directory = Path.GetDirectoryName(launcherPath); + Directory.SetCurrentDirectory(directory); + + AppDomain.CurrentDomain.UnhandledException += (_, e) => ExceptionHandler.HandleFatalError((Exception)e.ExceptionObject); + + try + { + return (int)Game.InitializeAndRun(args); + } + catch (Exception e) + { + // We must grant permission for the launcher process to bring the error dialog to the foreground. + // Finding the parent process id is unreasonably difficult on Windows, so instead pass -1 to enable for all processes. + AllowSetForegroundWindow(-1); + ExceptionHandler.HandleFatalError(e); + return (int)RunStatus.Error; + } + } + + static int RunInnerLauncher(string[] args) + { + var launcherPath = Process.GetCurrentProcess().MainModule.FileName; + var launcherArgs = args.ToList(); + + if (!launcherArgs.Any(x => x.StartsWith("Engine.LaunchPath=", StringComparison.Ordinal))) + launcherArgs.Add("Engine.LaunchPath=\"" + launcherPath + "\""); + + if (!launcherArgs.Any(x => x.StartsWith("Game.Mod=", StringComparison.Ordinal))) + launcherArgs.Add("Game.Mod=" + modID); + + var psi = new ProcessStartInfo(launcherPath, string.Join(" ", launcherArgs)); + + try + { + gameProcess = Process.Start(psi); + } + catch + { + return 1; + } + + if (gameProcess == null) + return 1; + + gameProcess.EnableRaisingEvents = true; + gameProcess.Exited += GameProcessExited; + gameProcess.WaitForExit(); + + return 0; + } + + static void ShowErrorDialog() + { + var viewLogs = new SDL.SDL_MessageBoxButtonData + { + buttonid = 2, + text = "View Logs", + flags = SDL.SDL_MessageBoxButtonFlags.SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT + }; + + var viewFaq = new SDL.SDL_MessageBoxButtonData + { + buttonid = 1, + text = "View FAQ" + }; + + var quit = new SDL.SDL_MessageBoxButtonData + { + buttonid = 0, + text = "Quit", + flags = SDL.SDL_MessageBoxButtonFlags.SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT + }; + + var dialog = new SDL.SDL_MessageBoxData + { + flags = SDL.SDL_MessageBoxFlags.SDL_MESSAGEBOX_ERROR, + title = "Fatal Error", + message = displayName + " has encountered a fatal error and must close.\nRefer to the crash logs and FAQ for more information.", + buttons = new[] { quit, viewFaq, viewLogs }, + numbuttons = 3 + }; + + // SDL_ShowMessageBox may create the error dialog behind other windows. + // We want to bring it to the foreground, but can't do it from the main thread + // because SDL_ShowMessageBox blocks until the user presses a button. + // HACK: Spawn a thread to raise it to the foreground after a short delay. + Task.Run(() => + { + Thread.Sleep(1000); + SetForegroundWindow(Process.GetCurrentProcess().MainWindowHandle); + }); + + if (SDL.SDL_ShowMessageBox(ref dialog, out var buttonid) < 0) + Exit(); + + switch (buttonid) + { + case 0: Exit(); break; + case 1: + { + try + { + Process.Start(faqUrl); + } + catch { } + break; + } + + case 2: + { + try + { + Process.Start(Path.Combine(Platform.SupportDir, "Logs")); + } + catch { } + break; + } + } + } + + static void GameProcessExited(object sender, EventArgs e) + { + if (gameProcess.ExitCode != (int)RunStatus.Success) + ShowErrorDialog(); + + Exit(); + } + + static void Exit() + { + Environment.Exit(0); + } + } +} diff --git a/OpenRA.sln b/OpenRA.sln index 1be8c442e7..6b732e68e2 100644 --- a/OpenRA.sln +++ b/OpenRA.sln @@ -21,6 +21,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenRA.Test", "OpenRA.Test\ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenRA.Launcher", "OpenRA.Launcher\OpenRA.Launcher.csproj", "{54DAE0E0-3125-49D3-992E-A0E931EB5FC8}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenRA.WindowsLauncher", "OpenRA.WindowsLauncher\OpenRA.WindowsLauncher.csproj", "{912B578E-0BC0-4987-807B-1E294A87DA37}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -63,6 +65,8 @@ Global {54DAE0E0-3125-49D3-992E-A0E931EB5FC8}.Debug|Any CPU.Build.0 = Debug|Any CPU {54DAE0E0-3125-49D3-992E-A0E931EB5FC8}.Release|Any CPU.ActiveCfg = Release|Any CPU {54DAE0E0-3125-49D3-992E-A0E931EB5FC8}.Release|Any CPU.Build.0 = Release|Any CPU + {912B578E-0BC0-4987-807B-1E294A87DA37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {912B578E-0BC0-4987-807B-1E294A87DA37}.Release|Any CPU.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/appveyor.yml b/appveyor.yml index 324d22cb68..f81557015a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -15,13 +15,10 @@ after_test: - python -c "from PIL import Image; i = Image.open('packaging/artwork/ra_256x256.png'); i.save('ra.ico')" - python -c "from PIL import Image; i = Image.open('packaging/artwork/cnc_256x256.png'); i.save('cnc.ico')" - python -c "from PIL import Image; i = Image.open('packaging/artwork/d2k_256x256.png'); i.save('d2k.ico')" + - msbuild -t:Build "OpenRA.WindowsLauncher/OpenRA.WindowsLauncher.csproj" -restore -p:Configuration=Release -p:TargetPlatform="win-x64" -p:LauncherName="RedAlert" -p:LauncherIcon="../ra.ico" -p:ModID="ra" -p:DisplayName="Red Alert" -p:FaqUrl="http://wiki.openra.net/FAQ" + - msbuild -t:Build "OpenRA.WindowsLauncher/OpenRA.WindowsLauncher.csproj" -restore -p:Configuration=Release -p:TargetPlatform="win-x64" -p:LauncherName="TiberianDawn" -p:LauncherIcon="../cnc.ico" -p:ModID="cnc" -p:DisplayName="Tiberian Dawn" -p:FaqUrl="http://wiki.openra.net/FAQ" + - msbuild -t:Build "OpenRA.WindowsLauncher/OpenRA.WindowsLauncher.csproj" -restore -p:Configuration=Release -p:TargetPlatform="win-x64" -p:LauncherName="Dune2000" -p:LauncherIcon="../d2k.ico" -p:ModID="d2k" -p:DisplayName="Dune 2000" -p:FaqUrl="http://wiki.openra.net/FAQ" - move /Y %APPVEYOR_BUILD_FOLDER%\bin\* %APPVEYOR_BUILD_FOLDER% - - ps: (Get-Content "${env:APPVEYOR_BUILD_FOLDER}\packaging\windows\WindowsLauncher.cs.in").replace('DISPLAY_NAME', 'Red Alert').replace('MOD_ID', 'ra').replace('FAQ_URL', 'http://wiki.openra.net/FAQ') | Set-Content "${env:APPVEYOR_BUILD_FOLDER}\packaging\windows\WindowsLauncher.cs" - - ps: C:\"Program Files (x86)"\"Microsoft Visual Studio"\2017\Community\MSBuild\15.0\Bin\Roslyn\csc.exe /noconfig /platform:x64 /reference:System.dll /reference:System.Core.dll /reference:System.Drawing.dll /reference:System.Windows.Forms.dll /reference:"${env:APPVEYOR_BUILD_FOLDER}\OpenRA.Game.dll" /out:"${env:APPVEYOR_BUILD_FOLDER}\RedAlert.exe" /win32icon:"${env:APPVEYOR_BUILD_FOLDER}\ra.ico" /target:winexe ${env:APPVEYOR_BUILD_FOLDER}\packaging\windows\WindowsLauncher.cs - - ps: (Get-Content "${env:APPVEYOR_BUILD_FOLDER}\packaging\windows\WindowsLauncher.cs.in").replace('DISPLAY_NAME', 'Tiberian Dawn').replace('MOD_ID', 'cnc').replace('FAQ_URL', 'http://wiki.openra.net/FAQ') | Set-Content "${env:APPVEYOR_BUILD_FOLDER}\packaging\windows\WindowsLauncher.cs" - - ps: C:\"Program Files (x86)"\"Microsoft Visual Studio"\2017\Community\MSBuild\15.0\Bin\Roslyn\csc.exe /noconfig /platform:x64 /reference:System.dll /reference:System.Core.dll /reference:System.Drawing.dll /reference:System.Windows.Forms.dll /reference:"${env:APPVEYOR_BUILD_FOLDER}\OpenRA.Game.dll" /out:"${env:APPVEYOR_BUILD_FOLDER}\TiberianDawn.exe" /win32icon:"${env:APPVEYOR_BUILD_FOLDER}\cnc.ico" /target:winexe ${env:APPVEYOR_BUILD_FOLDER}\packaging\windows\WindowsLauncher.cs - - ps: (Get-Content "${env:APPVEYOR_BUILD_FOLDER}\packaging\windows\WindowsLauncher.cs.in").replace('DISPLAY_NAME', 'Dune 2000').replace('MOD_ID', 'd2k').replace('FAQ_URL', 'http://wiki.openra.net/FAQ') | Set-Content "${env:APPVEYOR_BUILD_FOLDER}\packaging\windows\WindowsLauncher.cs" - - ps: C:\"Program Files (x86)"\"Microsoft Visual Studio"\2017\Community\MSBuild\15.0\Bin\Roslyn\csc.exe /noconfig /platform:x64 /reference:System.dll /reference:System.Core.dll /reference:System.Drawing.dll /reference:System.Windows.Forms.dll /reference:"${env:APPVEYOR_BUILD_FOLDER}\OpenRA.Game.dll" /out:"${env:APPVEYOR_BUILD_FOLDER}\Dune2000.exe" /win32icon:"${env:APPVEYOR_BUILD_FOLDER}\d2k.ico" /target:winexe ${env:APPVEYOR_BUILD_FOLDER}\packaging\windows\WindowsLauncher.cs - if defined APPVEYOR_REPO_TAG_NAME set VERSION=%APPVEYOR_REPO_TAG_NAME% - if not defined APPVEYOR_REPO_TAG_NAME set VERSION=%APPVEYOR_REPO_COMMIT:~0,7% - '"C:\Program Files (x86)\NSIS\makensis.exe" /DSRCDIR="%APPVEYOR_BUILD_FOLDER%" /DTAG="git-%VERSION%" /DSUFFIX=" (dev)" /V3 packaging/windows/OpenRA.nsi' diff --git a/packaging/windows/MakeLAA.cs b/packaging/windows/MakeLAA.cs deleted file mode 100644 index d03fcb55ff..0000000000 --- a/packaging/windows/MakeLAA.cs +++ /dev/null @@ -1,36 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2020 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation, either version 3 of - * the License, or (at your option) any later version. For more - * information, see COPYING. - */ -#endregion - -using System; -using System.IO; -using System.Linq; - -namespace OpenRA.PostProcess -{ - class Program - { - static void Main(string[] args) - { - var assembly = args.First(); - var flags = args.Skip(1).ToArray(); - - Console.WriteLine("Post-processing {0}", assembly); - var data = File.ReadAllBytes(assembly); - var peOffset = BitConverter.ToInt32(data, 0x3c); - - // Set /LARGEADDRESSAWARE Flag (Application can handle large (>2GB) addresses) - Console.WriteLine(" - Enabling /LARGEADDRESSAWARE"); - data[peOffset + 4 + 18] |= 0x20; - - File.WriteAllBytes(args[0], data); - } - } -} diff --git a/packaging/windows/MakeLAA.py b/packaging/windows/MakeLAA.py new file mode 100644 index 0000000000..c66f81fd2e --- /dev/null +++ b/packaging/windows/MakeLAA.py @@ -0,0 +1,19 @@ +# Copyright 2007-2020 The OpenRA Developers (see AUTHORS) +# This file is part of OpenRA, which is free software. It is made +# available to you under the terms of the GNU General Public License +# as published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. For more +# information, see COPYING. + +import struct +import sys + +if __name__ == "__main__": + print(sys.argv[1] + ': Enabling /LARGEADDRESSAWARE') + with open(sys.argv[1], 'r+b') as assembly: + assembly.seek(0x3c) + peOffset = struct.unpack('i', assembly.read(4))[0] + assembly.seek(peOffset + 4 + 18) + flags = struct.unpack('B', assembly.read(1))[0] | 0x20 + assembly.seek(peOffset + 4 + 18) + assembly.write(struct.pack('B', flags)) diff --git a/packaging/windows/WindowsLauncher.cs.in b/packaging/windows/WindowsLauncher.cs.in deleted file mode 100644 index 2a370e928b..0000000000 --- a/packaging/windows/WindowsLauncher.cs.in +++ /dev/null @@ -1,205 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2020 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation, either version 3 of - * the License, or (at your option) any later version. For more - * information, see COPYING. - */ -#endregion - -using System; -using System.Diagnostics; -using System.Drawing; -using System.IO; -using System.Linq; -using System.Media; -using System.Reflection; -using System.Windows.Forms; - -namespace OpenRA -{ - class WindowsLauncher - { - static Process gameProcess; - - // Constants to be replaced by the wrapper / compilation script - const string ModID = "MOD_ID"; - const string DisplayName = "DISPLAY_NAME"; - const string FaqUrl = "FAQ_URL"; - - [STAThread] - static int Main(string[] args) - { - if (args.Any(x => x.StartsWith("Engine.LaunchPath=", StringComparison.Ordinal))) - return RunGame(args); - - return RunInnerLauncher(args); - } - - static int RunGame(string[] args) - { - var launcherPath = Assembly.GetExecutingAssembly().Location; - var directory = Path.GetDirectoryName(launcherPath); - Directory.SetCurrentDirectory(directory); - - AppDomain.CurrentDomain.UnhandledException += (_, e) => ExceptionHandler.HandleFatalError((Exception)e.ExceptionObject); - - try - { - return (int)Game.InitializeAndRun(args); - } - catch (Exception e) - { - ExceptionHandler.HandleFatalError(e); - return (int)RunStatus.Error; - } - } - - static int RunInnerLauncher(string[] args) - { - var launcherPath = Assembly.GetExecutingAssembly().Location; - var launcherArgs = args.ToList(); - - if (!launcherArgs.Any(x => x.StartsWith("Engine.LaunchPath=", StringComparison.Ordinal))) - launcherArgs.Add("Engine.LaunchPath=\"" + launcherPath + "\""); - - if (!launcherArgs.Any(x => x.StartsWith("Game.Mod=", StringComparison.Ordinal))) - launcherArgs.Add("Game.Mod=" + ModID); - - var psi = new ProcessStartInfo(launcherPath, string.Join(" ", launcherArgs)); - - try - { - gameProcess = Process.Start(psi); - } - catch - { - return 1; - } - - if (gameProcess == null) - return 1; - - gameProcess.EnableRaisingEvents = true; - gameProcess.Exited += GameProcessExited; - - Application.Run(); - - return 0; - } - - static void ShowErrorDialog() - { - var headerLabel = new Label - { - Location = new Point(0, 10), - Height = 15, - Text = DisplayName + " has encountered a fatal error and must close.", - TextAlign = ContentAlignment.TopCenter - }; - - var docsLabel = new Label - { - Location = new Point(0, 25), - Height = 15, - Text = "Refer to the crash logs and FAQ for more information.", - TextAlign = ContentAlignment.TopCenter - }; - - int formWidth; - using (var g = headerLabel.CreateGraphics()) - { - var headerWidth = (int)g.MeasureString(headerLabel.Text, headerLabel.Font).Width + 60; - var docsWidth = (int)g.MeasureString(docsLabel.Text, docsLabel.Font).Width + 60; - formWidth = Math.Max(headerWidth, docsWidth); - headerLabel.Width = formWidth; - docsLabel.Width = formWidth; - } - - var form = new Form - { - Size = new Size(formWidth, 110), - Text = "Fatal Error", - MinimizeBox = false, - MaximizeBox = false, - FormBorderStyle = FormBorderStyle.FixedDialog, - StartPosition = FormStartPosition.CenterScreen, - TopLevel = true, - Icon = Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location) - }; - - var viewLogs = new Button - { - Location = new Point(10, 50), - Size = new Size(75, 23), - Text = "View Logs" - }; - - var viewFaq = new Button - { - Location = new Point(90, 50), - Size = new Size(75, 23), - Text = "View FAQ" - }; - - var quit = new Button - { - Location = new Point(formWidth - 90, 50), - Size = new Size(75, 23), - Text = "Quit", - DialogResult = DialogResult.Cancel - }; - - form.Controls.Add(headerLabel); - form.Controls.Add(docsLabel); - form.Controls.Add(viewLogs); - form.Controls.Add(viewFaq); - form.Controls.Add(quit); - - viewLogs.Click += ViewLogsClicked; - viewFaq.Click += ViewFaqClicked; - form.FormClosed += FormClosed; - - SystemSounds.Exclamation.Play(); - form.ShowDialog(); - } - - static void GameProcessExited(object sender, EventArgs e) - { - if (gameProcess.ExitCode != (int)RunStatus.Success) - ShowErrorDialog(); - - Exit(); - } - - static void ViewLogsClicked(object sender, EventArgs e) - { - try - { - Process.Start(Path.Combine(Platform.SupportDir, "Logs")); - } - catch { } - } - - static void ViewFaqClicked(object sender, EventArgs e) - { - try - { - Process.Start(FaqUrl); - } - catch { } - } - - static void FormClosed(object sender, EventArgs e) - { - Exit(); - } - - static void Exit() - { - Environment.Exit(0); - } - } -} diff --git a/packaging/windows/buildpackage.sh b/packaging/windows/buildpackage.sh index 92c7309b55..040c145575 100755 --- a/packaging/windows/buildpackage.sh +++ b/packaging/windows/buildpackage.sh @@ -3,6 +3,7 @@ command -v curl >/dev/null 2>&1 || { echo >&2 "Windows packaging requires curl."; exit 1; } command -v makensis >/dev/null 2>&1 || { echo >&2 "Windows packaging requires makensis."; exit 1; } command -v convert >/dev/null 2>&1 || { echo >&2 "Windows packaging requires ImageMagick."; exit 1; } +command -v python3 >/dev/null 2>&1 || { echo >&2 "Windows packaging requires python 3."; exit 1; } if [ $# -ne "2" ]; then echo "Usage: $(basename "$0") tag outputdir" @@ -38,20 +39,15 @@ function makelauncher() # Create multi-resolution icon convert "${ARTWORK_DIR}/${MOD_ID}_16x16.png" "${ARTWORK_DIR}/${MOD_ID}_24x24.png" "${ARTWORK_DIR}/${MOD_ID}_32x32.png" "${ARTWORK_DIR}/${MOD_ID}_48x48.png" "${ARTWORK_DIR}/${MOD_ID}_256x256.png" "${BUILTDIR}/${MOD_ID}.ico" - sed "s|DISPLAY_NAME|${DISPLAY_NAME}|" WindowsLauncher.cs.in | sed "s|MOD_ID|${MOD_ID}|" | sed "s|FAQ_URL|${FAQ_URL}|" > WindowsLauncher.cs - csc WindowsLauncher.cs -warn:4 -warnaserror -platform:"${PLATFORM}" -out:"${BUILTDIR}/${LAUNCHER_NAME}" -t:winexe ${LAUNCHER_LIBS} -win32icon:"${BUILTDIR}/${MOD_ID}.ico" - rm WindowsLauncher.cs + # Create mod-specific launcher + msbuild -t:Build "${SRCDIR}/OpenRA.WindowsLauncher/OpenRA.WindowsLauncher.csproj" -restore -p:Configuration=Release -p:TargetPlatform="${PLATFORM}" -p:LauncherName="${LAUNCHER_NAME}" -p:LauncherIcon="${BUILTDIR}/${MOD_ID}.ico" -p:ModID="${MOD_ID}" -p:DisplayName="${DISPLAY_NAME}" -p:FaqUrl="${FAQ_URL}" + cp "${SRCDIR}/bin/${LAUNCHER_NAME}.exe" "${BUILTDIR}" + cp "${SRCDIR}/bin/${LAUNCHER_NAME}.exe.config" "${BUILTDIR}" - # We need to set the loadFromRemoteSources flag for the launcher, but only for the "portable" zip package. - # Windows automatically un-trusts executables that are extracted from a downloaded zip file - cp "${BUILTDIR}/OpenRA.exe.config" "${BUILTDIR}/${LAUNCHER_NAME}.config" - - if [ "${PLATFORM}" = "x86" ]; then - # Enable the full 4GB address space for the 32 bit game executable - # The server and utility do not use enough memory to need this - csc MakeLAA.cs -warn:4 -warnaserror -out:"MakeLAA.exe" - mono "MakeLAA.exe" "${BUILTDIR}/${LAUNCHER_NAME}" - rm MakeLAA.exe + # Enable the full 4GB address space for the 32 bit game executable + # The server and utility do not use enough memory to need this + if [ "${PLATFORM}" = "win-x86" ]; then + python3 MakeLAA.py "${BUILTDIR}/${LAUNCHER_NAME}.exe" fi } @@ -60,32 +56,29 @@ function build_platform() PLATFORM="${1}" echo "Building core files (${PLATFORM})" - if [ "${PLATFORM}" = "x86" ]; then - TARGETPLATFORM="TARGETPLATFORM=win-x86" - IS_WIN32="WIN32=true" + if [ "${PLATFORM}" = "win-x86" ]; then USE_PROGRAMFILES32="-DUSE_PROGRAMFILES32=true" else - IS_WIN32="WIN32=false" - TARGETPLATFORM="TARGETPLATFORM=win-x64" USE_PROGRAMFILES32="" fi pushd "${SRCDIR}" > /dev/null || exit 1 make clean - make core "${TARGETPLATFORM}" "${IS_WIN32}" + make core TARGETPLATFORM="${PLATFORM}" make version VERSION="${TAG}" - make install-engine "${TARGETPLATFORM}" gameinstalldir="" DESTDIR="${BUILTDIR}" + make install-engine TARGETPLATFORM="${PLATFORM}" gameinstalldir="" DESTDIR="${BUILTDIR}" make install-common-mod-files gameinstalldir="" DESTDIR="${BUILTDIR}" make install-default-mods gameinstalldir="" DESTDIR="${BUILTDIR}" - make install-dependencies "${TARGETPLATFORM}" gameinstalldir="" DESTDIR="${BUILTDIR}" + make install-dependencies TARGETPLATFORM="${PLATFORM}" gameinstalldir="" DESTDIR="${BUILTDIR}" popd > /dev/null || exit 1 - cp "${SRCDIR}/bin/OpenRA.exe.config" "${BUILTDIR}" - echo "Compiling Windows launchers (${PLATFORM})" - makelauncher "RedAlert.exe" "Red Alert" "ra" ${PLATFORM} - makelauncher "TiberianDawn.exe" "Tiberian Dawn" "cnc" ${PLATFORM} - makelauncher "Dune2000.exe" "Dune 2000" "d2k" ${PLATFORM} + makelauncher "RedAlert" "Red Alert" "ra" ${PLATFORM} + makelauncher "TiberianDawn" "Tiberian Dawn" "cnc" ${PLATFORM} + makelauncher "Dune2000" "Dune 2000" "d2k" ${PLATFORM} + + # Remove redundant generic launcher + rm "${BUILTDIR}/OpenRA.exe" echo "Building Windows setup.exe ($1)" makensis -V2 -DSRCDIR="${BUILTDIR}" -DTAG="${TAG}" -DSUFFIX="${SUFFIX}" ${USE_PROGRAMFILES32} OpenRA.nsi @@ -104,5 +97,5 @@ function build_platform() rm -rf "${BUILTDIR}" } -build_platform "x86" -build_platform "x64" +build_platform "win-x86" +build_platform "win-x64"