From 316f6bbef0b82fcc9c50f8b37a7c6a1643456e72 Mon Sep 17 00:00:00 2001 From: Eddoursul Date: Sat, 2 Mar 2024 14:39:18 +0100 Subject: [PATCH] Initial commit --- .gitignore | 7 + EnderalInstaller.iss | 319 +++++++++++++++++++++++++++++++++++++++++++ enderal.ico | Bin 0 -> 31702 bytes 3 files changed, 326 insertions(+) create mode 100644 .gitignore create mode 100644 EnderalInstaller.iss create mode 100644 enderal.ico diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..827e08c --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +/base +/Output +/skse +/*.chm +/*.chw +/*.exe +/*.cmd diff --git a/EnderalInstaller.iss b/EnderalInstaller.iss new file mode 100644 index 0000000..5700c5e --- /dev/null +++ b/EnderalInstaller.iss @@ -0,0 +1,319 @@ +#define RemoteHost GetEnv('REMOTE_HOST') +#define RemoteVersionDir GetEnv('REMOTE_DIR_VERSIONED') +#define RemoteMediaDir GetEnv('REMOTE_DIR_MEDIA') + +[Setup] +AppName=Enderal SE +DefaultGroupName=Enderal SE +AppVersion=2.1.0 +AppVerName=Enderal SE 2.1 [mod.pub] +AppPublisher=ModPub +AppPublisherURL=https://mod.pub/ +AppReadmeFile=https://mod.pub/enderal-se/38-enderal-se +AppSupportURL=https://mod.pub/enderal-se/38/comments +AppUpdatesURL=https://mod.pub/enderal-se/38/files +WizardStyle=modern +DefaultDirName={drive:{src}}\Games\Enderal SE +ArchitecturesAllowed=x64 +OutputBaseFilename=EnderalSE_Install +ExtraDiskSpaceRequired=20204613632 +AllowNetworkDrive=no +Compression=lzma2/max +SolidCompression=yes +SetupIconFile=enderal.ico +UninstallDisplayName=Enderal SE +UninstallDisplayIcon={app}\Game\Data\enderal.ico +DisableWelcomePage=yes +DisableDirPage=no +DisableProgramGroupPage=no +AllowNoIcons=yes + +[Files] +; Root +Source: "{code:GetSkyrimPath}\SkyrimSE.exe"; DestDir: "{app}\Game"; Flags: external ignoreversion +Source: "{code:GetSkyrimPath}\SkyrimSELauncher.exe"; DestDir: "{app}\Game"; Check: IsNotVR(); Flags: external ignoreversion + +Source: "{code:GetSkyrimPath}\SkyrimVR.exe"; DestDir: "{app}\Game"; Check: IsVR(); Flags: external ignoreversion +Source: "{code:GetSkyrimPath}\openvr_api.dll"; DestDir: "{app}\Game"; Check: IsVR(); Flags: external ignoreversion +Source: "{code:GetSkyrimPath}\atimgpud.dll"; DestDir: "{app}\Game"; Check: IsVR(); Flags: external ignoreversion + +Source: "{code:GetSkyrimPath}\steam_api64.dll"; DestDir: "{app}\Game"; Check: IsSteam(); Flags: external ignoreversion +Source: "{code:GetSkyrimPath}\Galaxy64.dll"; DestDir: "{app}\Game"; Check: IsGOG(); Flags: external ignoreversion +Source: "{code:GetSkyrimPath}\binkw64.dll"; DestDir: "{app}\Game"; Flags: external skipifsourcedoesntexist ignoreversion +Source: "{code:GetSkyrimPath}\bink2w64.dll"; DestDir: "{app}\Game"; Flags: external skipifsourcedoesntexist ignoreversion + +Source: "{code:GetSkyrimPath}\ControlMap_Custom.txt"; DestDir: "{app}\Game"; Flags: external skipifsourcedoesntexist +Source: "{code:GetSkyrimPath}\Skyrim_Default.ini"; DestDir: "{app}\Game"; Flags: external skipifsourcedoesntexist +Source: "{code:GetSkyrimPath}\High.ini"; DestDir: "{app}\Game"; Flags: external skipifsourcedoesntexist +Source: "{code:GetSkyrimPath}\Low.ini"; DestDir: "{app}\Game"; Flags: external skipifsourcedoesntexist +Source: "{code:GetSkyrimPath}\Medium.ini"; DestDir: "{app}\Game"; Flags: external skipifsourcedoesntexist +Source: "{code:GetSkyrimPath}\Ultra.ini"; DestDir: "{app}\Game"; Flags: external skipifsourcedoesntexist + +; Data +Source: "{code:GetSkyrimPath}\Data\Skyrim - Animations.bsa"; DestDir: "{app}\Game\Data"; Flags: external comparetimestamp +Source: "{code:GetSkyrimPath}\Data\Skyrim - Interface.bsa"; DestDir: "{app}\Game\Data"; Flags: external comparetimestamp +Source: "{code:GetSkyrimPath}\Data\Skyrim - Meshes0.bsa"; DestDir: "{app}\Game\Data"; Flags: external comparetimestamp +Source: "{code:GetSkyrimPath}\Data\Skyrim - Meshes1.bsa"; DestDir: "{app}\Game\Data"; Flags: external comparetimestamp +Source: "{code:GetSkyrimPath}\Data\Skyrim - Shaders.bsa"; DestDir: "{app}\Game\Data"; Flags: external comparetimestamp +Source: "{code:GetSkyrimPath}\Data\Skyrim - Sounds.bsa"; DestDir: "{app}\Game\Data"; Flags: external comparetimestamp +Source: "{code:GetSkyrimPath}\Data\Skyrim - Textures0.bsa"; DestDir: "{app}\Game\Data"; Flags: external comparetimestamp +Source: "{code:GetSkyrimPath}\Data\Skyrim - Textures1.bsa"; DestDir: "{app}\Game\Data"; Flags: external comparetimestamp +Source: "{code:GetSkyrimPath}\Data\Skyrim - Textures2.bsa"; DestDir: "{app}\Game\Data"; Flags: external comparetimestamp +Source: "{code:GetSkyrimPath}\Data\Skyrim - Textures3.bsa"; DestDir: "{app}\Game\Data"; Flags: external comparetimestamp +Source: "{code:GetSkyrimPath}\Data\Skyrim - Textures4.bsa"; DestDir: "{app}\Game\Data"; Flags: external comparetimestamp +Source: "{code:GetSkyrimPath}\Data\Skyrim - Textures5.bsa"; DestDir: "{app}\Game\Data"; Flags: external comparetimestamp +Source: "{code:GetSkyrimPath}\Data\Skyrim - Textures6.bsa"; DestDir: "{app}\Game\Data"; Flags: external comparetimestamp +Source: "{code:GetSkyrimPath}\Data\Skyrim - Textures7.bsa"; DestDir: "{app}\Game\Data"; Flags: external comparetimestamp +Source: "{code:GetSkyrimPath}\Data\Skyrim - Textures8.bsa"; DestDir: "{app}\Game\Data"; Flags: external comparetimestamp +Source: "{code:GetSkyrimPath}\Data\Skyrim - Patch.bsa"; DestDir: "{app}\Game\Data"; Flags: external comparetimestamp skipifsourcedoesntexist +Source: "{code:GetSkyrimPath}\Data\Skyrim_VR - Main.bsa"; DestDir: "{app}\Game\Data"; Check: IsVR(); Flags: external comparetimestamp + +; Enderal +Source: "base\*"; DestDir: "{app}\Game\Data"; Excludes: "*.esl,ccBGSSSE001-Fish.esm,ccBGSSSE025-AdvDSGS.esm,E - Meshes.bsa,E - Sounds.bsa,E - Textures1.bsa,E - Textures2.bsa,L - Voices.bsa,Enderal_Credits.bik,EnderalIntro.bik,MQ17BlackGuardian.bik,MQP03NearDeathExperience.bik"; Flags: recursesubdirs ignoreversion + +; SKSE +Source: "skse\1.4.15.0\*"; DestDir: "{app}\Game"; Check: IsSkyrimVersion('1.4.15.0'); Flags: ignoreversion +Source: "skse\1.5.97.0\*"; DestDir: "{app}\Game"; Check: IsSkyrimVersion('1.5.97.0'); Flags: ignoreversion +Source: "skse\1.6.640.0\*"; DestDir: "{app}\Game"; Check: IsSkyrimVersion('1.6.640.0'); Flags: ignoreversion +Source: "skse\1.6.659.0\*"; DestDir: "{app}\Game"; Check: IsSkyrimVersion('1.6.659.0'); Flags: ignoreversion +Source: "skse\1.6.1130.0\*"; DestDir: "{app}\Game"; Check: IsSkyrimVersion('1.6.1130.0'); Flags: ignoreversion +Source: "skse\1.6.1170.0\*"; DestDir: "{app}\Game"; Check: IsSkyrimVersion('1.6.1170.0'); Flags: ignoreversion +Source: "skse\1.6.1179.0\*"; DestDir: "{app}\Game"; Check: IsSkyrimVersion('1.6.1179.0'); Flags: ignoreversion + +Source: "wget.exe"; DestDir: "{app}"; Flags: deleteafterinstall ignoreversion +Source: "modlhandler.exe"; DestDir: "{app}\MO2"; Flags: uninsneveruninstall ignoreversion + +[InstallDelete] +Type: files; Name: "{app}\Game\SkyrimSE.exe" +Type: files; Name: "{app}\Game\SkyrimSELauncher.exe" +Type: files; Name: "{app}\Game\SkyrimVR.exe" +Type: files; Name: "{app}\Game\sksevr_*.dll" +Type: files; Name: "{app}\Game\skse64_*.dll" +Type: files; Name: "{app}\Game\skse*_steam_loader.dll" +Type: files; Name: "{app}\Game\steam_api64.dll" +Type: files; Name: "{app}\Game\Galaxy64.dll" +Type: files; Name: "{app}\Game\binkw64.dll" +Type: files; Name: "{app}\Game\bink2w64.dll" +Type: files; Name: "{app}\Game\openvr_api.dll" +Type: files; Name: "{app}\Game\atimgpud.dll" +Type: files; Name: "{app}\Game\Data\SkyrimVR.esm" + +[UninstallDelete] +Type: files; Name: "{app}\Game\Data\E - Meshes.bsa" +Type: files; Name: "{app}\Game\Data\E - Sounds.bsa" +Type: files; Name: "{app}\Game\Data\E - Textures1.bsa" +Type: files; Name: "{app}\Game\Data\E - Textures2.bsa" +Type: files; Name: "{app}\Game\Data\L - Voices.bsa" + +Type: files; Name: "{app}\Game\Data\Video\Enderal_Credits.bik" +Type: files; Name: "{app}\Game\Data\Video\EnderalIntro.bik" +Type: files; Name: "{app}\Game\Data\Video\MQ17BlackGuardian.bik" +Type: files; Name: "{app}\Game\Data\Video\MQP03NearDeathExperience.bik" + +Type: dirifempty; Name: "{app}\Game\Data" +Type: dirifempty; Name: "{app}\Game\Creations" +Type: dirifempty; Name: "{app}\Game\Mods" +Type: dirifempty; Name: "{app}\Game" + +[Run] +Filename: "{app}\wget.exe"; StatusMsg: "Downloading E - Meshes.bsa (1.48 Gb)..."; Parameters: "-nd -N -P ""{app}\Game\Data"" ""{#RemoteHost}/{#RemoteVersionDir}/E%20-%20Meshes.bsa"""; Flags: runhidden +Filename: "{app}\wget.exe"; StatusMsg: "Downloading E - Textures1.bsa (1.7 Gb)..."; Parameters: "-nd -N -P ""{app}\Game\Data"" ""{#RemoteHost}/{#RemoteVersionDir}/E%20-%20Textures1.bsa"""; Flags: runhidden +Filename: "{app}\wget.exe"; StatusMsg: "Downloading E - Textures2.bsa (1.72 Gb)..."; Parameters: "-nd -N -P ""{app}\Game\Data"" ""{#RemoteHost}/{#RemoteVersionDir}/E%20-%20Textures2.bsa"""; Flags: runhidden + +Filename: "{app}\wget.exe"; StatusMsg: "Downloading E - Sounds.bsa (1.3 Gb)..."; Parameters: "-nd -N -P ""{app}\Game\Data"" ""{#RemoteHost}/{#RemoteMediaDir}/E%20-%20Sounds.bsa"""; Flags: runhidden +Filename: "{app}\wget.exe"; StatusMsg: "Downloading L - Voices.bsa (1.38 Gb)..."; Parameters: "-nd -N -P ""{app}\Game\Data"" ""{#RemoteHost}/{#RemoteMediaDir}/L%20-%20Voices.bsa"""; Flags: runhidden + +Filename: "{app}\wget.exe"; StatusMsg: "Downloading Enderal_Credits.bik (1.29 Gb)..."; Parameters: "-nd -N -P ""{app}\Game\Data\Video"" ""{#RemoteHost}/{#RemoteMediaDir}/Video/Enderal_Credits.bik"""; Check: IsNotVR(); Flags: runhidden +Filename: "{app}\wget.exe"; StatusMsg: "Downloading EnderalIntro.bik (275 Mb)..."; Parameters: "-nd -N -P ""{app}\Game\Data\Video"" ""{#RemoteHost}/{#RemoteMediaDir}/Video/EnderalIntro.bik"""; Check: IsNotVR(); Flags: runhidden +Filename: "{app}\wget.exe"; StatusMsg: "Downloading MQ17BlackGuardian.bik (474 Mb)..."; Parameters: "-nd -N -P ""{app}\Game\Data\Video"" ""{#RemoteHost}/{#RemoteMediaDir}/Video/MQ17BlackGuardian.bik"""; Check: IsNotVR(); Flags: runhidden +Filename: "{app}\wget.exe"; StatusMsg: "Downloading MQP03NearDeathExperience.bik (38 Mb)..."; Parameters: "-nd -N -P ""{app}\Game\Data\Video"" ""{#RemoteHost}/{#RemoteMediaDir}/Video/MQP03NearDeathExperience.bik"""; Check: IsNotVR(); Flags: runhidden + +Filename: "{tmp}\Mod.Organizer-2.5.0.exe"; Parameters: "/SILENT /DIR=""{app}\MO2""" +Filename: "{app}\MO2\modlhandler.exe"; Parameters: "forcereg"; Flags: runhidden +Filename: "{cmd}"; Parameters: "/d /c del /s /q ""{tmp}\Mod.Organizer-2.5.0.exe"""; Flags: runhidden + +Filename: "{app}\MO2\ModOrganizer.exe"; Parameters: """moshortcut://:SKSE"""; Description: "Launch Enderal SE"; Flags: postinstall +Filename: "https://mod.pub/enderal-se/38/changelogs"; Description: "See changelog"; Flags: shellexec postinstall runmaximized + +[INI] +Filename: "{app}\MO2\ModOrganizer.ini"; Section: "General"; Key: "gameName"; String: "Skyrim VR"; Check: IsVR() +Filename: "{app}\MO2\ModOrganizer.ini"; Section: "General"; Key: "gameName"; String: "Skyrim Special Edition"; Check: IsNotVR() +Filename: "{app}\MO2\ModOrganizer.ini"; Section: "General"; Key: "first_start"; String: "false" +Filename: "{app}\MO2\ModOrganizer.ini"; Section: "General"; Key: "selected_profile"; String: "@ByteArray(Default)"; Flags: createkeyifdoesntexist +Filename: "{app}\MO2\ModOrganizer.ini"; Section: "General"; Key: "game_edition"; String: "Steam"; Check: IsSteam() +Filename: "{app}\MO2\ModOrganizer.ini"; Section: "General"; Key: "game_edition"; String: "GOG"; Check: IsGOG() +Filename: "{app}\MO2\ModOrganizer.ini"; Section: "General"; Key: "gamePath"; String: "@ByteArray({code:DoubleBackslashes|{app}}\\Game)" +Filename: "{app}\MO2\ModOrganizer.ini"; Section: "General"; Key: "version"; String: "2.5" + +Filename: "{app}\MO2\ModOrganizer.ini"; Section: "Settings"; Key: "profile_local_inis"; String: "true" +Filename: "{app}\MO2\ModOrganizer.ini"; Section: "Settings"; Key: "profile_local_saves"; String: "true" +Filename: "{app}\MO2\ModOrganizer.ini"; Section: "Settings"; Key: "profile_archive_invalidation"; String: "true" +Filename: "{app}\MO2\ModOrganizer.ini"; Section: "Settings"; Key: "compact_downloads"; String: "true"; Flags: createkeyifdoesntexist +Filename: "{app}\MO2\ModOrganizer.ini"; Section: "Settings"; Key: "category_mappings"; String: "false"; Flags: createkeyifdoesntexist +Filename: "{app}\MO2\ModOrganizer.ini"; Section: "Settings"; Key: "base_directory"; String: "{code:ConvertBackslashes|{app}}/Data" + +Filename: "{app}\Data\profiles\Default\skyrimprefs.ini"; Section: "Display"; Key: "iShadowMaskQuarter"; String: "4" +Filename: "{app}\Data\profiles\Default\skyrimprefs.ini"; Section: "Controls"; Key: "fMouseHeadingSensitivity"; String: "0.0420"; Flags: createkeyifdoesntexist + +[Icons] +Name: "{userdesktop}\Enderal SE"; Filename: "{app}\MO2\ModOrganizer.exe"; WorkingDir: "{app}\MO2"; Parameters: """moshortcut://:SKSE"""; IconFilename: "{app}\Game\Data\enderal.ico" +Name: "{app}\Run Enderal SE"; Filename: "{app}\MO2\ModOrganizer.exe"; WorkingDir: "{app}\MO2"; Parameters: """moshortcut://:SKSE"""; IconFilename: "{app}\Game\Data\enderal.ico" +Name: "{group}\Run Enderal SE"; Filename: "{app}\MO2\ModOrganizer.exe"; WorkingDir: "{app}\MO2"; Parameters: """moshortcut://:SKSE"""; IconFilename: "{app}\Game\Data\enderal.ico" +Name: "{group}\Manage mods"; Filename: "{app}\MO2\ModOrganizer.exe"; WorkingDir: "{app}\MO2"; Flags: runmaximized +Name: "{group}\Uninstall"; Filename: "{uninstallexe}" + +[Registry] +Root: HKLM; Subkey: "SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers"; ValueType: String; ValueName: "{app}\MO2\ModOrganizer.exe"; ValueData: "RUNASADMIN"; Flags: uninsdeletekeyifempty uninsdeletevalue; MinVersion: 0,6.1 +Root: HKCU; Subkey: "SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers"; ValueType: String; ValueName: "{app}\MO2\ModOrganizer.exe"; ValueData: "RUNASADMIN"; Flags: uninsdeletekeyifempty uninsdeletevalue; MinVersion: 0,6.1 +Root: HKCU; Subkey: "Software\SureAI\EnderalSE"; ValueType: string; ValueName: "Install_Path"; ValueData: "{app}\Game\" + +[Code] +var + SkyrimDirPage: TInputDirWizardPage; + DownloadPage: TDownloadWizardPage; + sSkyrimPath, sSkyrimVersion: String; + +function IsSkyrimVersion(Param: String): Boolean; +begin + if sSkyrimVersion = Param then + Result := True; +end; + +function IsGOG(): Boolean; +begin + Result := (sSkyrimVersion = '1.6.659.0') or (sSkyrimVersion = '1.6.1179.0'); +end; + +function IsVR(): Boolean; +begin + Result := (sSkyrimVersion = '1.4.15.0'); +end; + +function IsNotVR(): Boolean; +begin + Result := not IsVR(); +end; + +function IsSteam(): Boolean; +begin + Result := (not IsGOG()) and (not IsVR()); +end; + +function GetSkyrimPath(Param: String): String; +begin + Result := sSkyrimPath; +end; + +function ConvertBackslashes(Param: String): String; +begin + StringChangeEx(Param, '\', '/', True); + Result := Param; +end; + +function DoubleBackslashes(Param: String): String; +begin + StringChangeEx(Param, '\', '\\', True); + Result := Param; +end; + +function OnDownloadProgress(const Url, FileName: String; const Progress, ProgressMax: Int64): Boolean; +begin + if Progress = ProgressMax then + Log(Format('Successfully downloaded file to {tmp}: %s', [FileName])); + Result := True; +end; + +function FindSkyrimPath(): Boolean; +begin + Result := True; + if not RegQueryStringValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\Bethesda Softworks\Skyrim Special Edition GOG', 'Installed Path', sSkyrimPath) then + if not RegQueryStringValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\Bethesda Softworks\Skyrim Special Edition', 'Installed Path', sSkyrimPath) then + if not RegQueryStringValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\Bethesda Softworks\Skyrim VR', 'Installed Path', sSkyrimPath) then + Result := False; +end; + +procedure InitializeWizard; +begin + FindSkyrimPath(); + + SkyrimDirPage := CreateInputDirPage(wpSelectTasks, 'Skyrim SE location', 'All necessary files will be copied to the Enderal SE directory, creating a new copy of Skyrim. The original Skyrim installation will not be modified.', '', False, ''); + SkyrimDirPage.Add('Select a directory with installed Skyrim Special Edition:'); + SkyrimDirPage.Values[0] := RemoveBackslashUnlessRoot(sSkyrimPath); + + DownloadPage := CreateDownloadPage(SetupMessage(msgWizardPreparing), SetupMessage(msgPreparingDesc), @OnDownloadProgress); +end; + +function NextButtonClick(CurPageID: Integer): Boolean; +var + supportedVersions: TStringList; +begin + if CurPageID = SkyrimDirPage.ID then begin + sSkyrimPath := RemoveBackslashUnlessRoot(SkyrimDirPage.Values[0]) + '\'; + + if not GetVersionNumbersString(sSkyrimPath + 'SkyrimSE.exe', sSkyrimVersion) then begin + Result := False; + MsgBox('Please, select a directory with installed Skyrim Special Edition.', mbError, MB_OK); + Exit; + end + else if (sSkyrimVersion = '1.0.0.0') and FileExists(sSkyrimPath + 'binkw64.dll') then begin + if FileExists(sSkyrimPath + 'SkyrimVR.exe') then + sSkyrimVersion := '1.4.15.0' + else + sSkyrimVersion := '1.5.97.0'; + end; + + StringChangeEx(sSkyrimVersion, ' ', '', True); + + supportedVersions := TStringList.Create; + supportedVersions.Add('1.4.15.0'); + supportedVersions.Add('1.5.97.0'); + supportedVersions.Add('1.6.640.0'); + supportedVersions.Add('1.6.659.0'); + supportedVersions.Add('1.6.1130.0'); + supportedVersions.Add('1.6.1170.0'); + supportedVersions.Add('1.6.1179.0'); + + if supportedVersions.IndexOf(sSkyrimVersion) < 0 then begin + Result := False; + MsgBox('Skyrim SE ' + sSkyrimVersion + ' is untested with this version of Enderal SE.', mbError, MB_OK); + Exit; + end; + end; + + if CurPageID = wpReady then begin + if not FileExists(ExpandConstant('{app}') + '\Data\profiles\Default\plugins.txt') then begin + ForceDirectories(ExpandConstant('{app}') + '\Data\profiles\Default'); + SaveStringToFile(ExpandConstant('{app}') + '\Data\profiles\Default\plugins.txt', '# This file was automatically generated by Mod Organizer.' + #13#10 + '*Enderal - Forgotten Stories.esm' + #13#10, False); + end; + + DownloadPage.Clear; + DownloadPage.Add('https://github.com/ModOrganizer2/modorganizer/releases/download/v2.5.0/Mod.Organizer-2.5.0.exe', 'Mod.Organizer-2.5.0.exe', ''); + DownloadPage.Show; + try + try + DownloadPage.Download; // This downloads the files to {tmp} + Result := True; + except + if DownloadPage.AbortedByUser then + Log('Aborted by user.') + else + SuppressibleMsgBox(AddPeriod(GetExceptionMessage), mbCriticalError, MB_OK, IDOK); + Result := False; + end; + finally + DownloadPage.Hide; + end; + end else + Result := True; +end; + +function UpdateReadyMemo(Space, NewLine, MemoUserInfoInfo, MemoDirInfo, MemoTypeInfo, MemoComponentsInfo, MemoGroupInfo, MemoTasksInfo: String): String; +var + S: String; +begin + S := MemoDirInfo; + S := S + NewLine + NewLine + 'Skyrim location:'; + S := S + NewLine + Space + RemoveBackslashUnlessRoot(sSkyrimPath); + S := S + NewLine + Space + 'v' + sSkyrimVersion; + Result := S; +end; diff --git a/enderal.ico b/enderal.ico new file mode 100644 index 0000000000000000000000000000000000000000..d3c716c01185aeda575239a5ee8941bb68e2b148 GIT binary patch literal 31702 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