diff --git a/Launcher/lib/+UnFurl.cmd b/Launcher/lib/+UnFurl.cmd new file mode 100644 index 0000000..598e3c6 --- /dev/null +++ b/Launcher/lib/+UnFurl.cmd @@ -0,0 +1,2 @@ +unfurl3.exe +pause \ No newline at end of file diff --git a/Launcher/lib/UnFurl exit codes.txt b/Launcher/lib/UnFurl exit codes.txt new file mode 100644 index 0000000..3c8807b --- /dev/null +++ b/Launcher/lib/UnFurl exit codes.txt @@ -0,0 +1,13 @@ +0 Successful operation. +1 Warning. Non fatal error(s) occurred. +2 A fatal error occurred. +3 Invalid checksum. Data is damaged. +4 Attempt to modify a locked archive. +5 Write error. +6 File open error. +7 Wrong command line option. +8 Not enough memory. +9 File create error. +10 No files matching the specified mask and options were found. +11 Wrong password. +255 User break. diff --git a/Launcher/lib/UnFurl3.exe b/Launcher/lib/UnFurl3.exe new file mode 100644 index 0000000..5df3208 Binary files /dev/null and b/Launcher/lib/UnFurl3.exe differ diff --git a/Launcher/lib/hashvalidate.ahk b/Launcher/lib/hashvalidate.ahk new file mode 100644 index 0000000..37e8255 --- /dev/null +++ b/Launcher/lib/hashvalidate.ahk @@ -0,0 +1,93 @@ +/* +HASH types: +1 - MD2 +2 - MD5 +3 - SHA +4 - SHA256 - not supported on XP,2000 +5 - SHA384 - not supported on XP,2000 +6 - SHA512 - not supported on XP,2000 +*/ +HashFile(filePath,hashType=2) ; By Deo, http://www.autohotkey.com/forum/viewtopic.php?t=71133 +{ + PROV_RSA_AES := 24 + CRYPT_VERIFYCONTEXT := 0xF0000000 + BUFF_SIZE := 1024 * 1024 ; 1 MB + HP_HASHVAL := 0x0002 + HP_HASHSIZE := 0x0004 + + HASH_ALG := (hashType = 1 OR hashType = "MD2") ? (CALG_MD2 := 32769) : HASH_ALG + HASH_ALG := (hashType = 2 OR hashType = "MD5") ? (CALG_MD5 := 32771) : HASH_ALG + HASH_ALG := (hashType = 3 OR hashType = "SHA") ? (CALG_SHA := 32772) : HASH_ALG + HASH_ALG := (hashType = 4 OR hashType = "SHA256") ? (CALG_SHA_256 := 32780) : HASH_ALG ;Vista+ only + HASH_ALG := (hashType = 5 OR hashType = "SHA384") ? (CALG_SHA_384 := 32781) : HASH_ALG ;Vista+ only + HASH_ALG := (hashType = 6 OR hashType = "SHA512") ? (CALG_SHA_512 := 32782) : HASH_ALG ;Vista+ only + + f := FileOpen(filePath,"r","CP0") + if !IsObject(f) + return 0 + if !hModule := DllCall( "GetModuleHandleW", "str", "Advapi32.dll", "Ptr" ) + hModule := DllCall( "LoadLibraryW", "str", "Advapi32.dll", "Ptr" ) + if !dllCall("Advapi32\CryptAcquireContextW" + ,"Ptr*",hCryptProv + ,"Uint",0 + ,"Uint",0 + ,"Uint",PROV_RSA_AES + ,"UInt",CRYPT_VERIFYCONTEXT ) + Gosub,HashTypeFreeHandles + + if !dllCall("Advapi32\CryptCreateHash" + ,"Ptr",hCryptProv + ,"Uint",HASH_ALG + ,"Uint",0 + ,"Uint",0 + ,"Ptr*",hHash ) + Gosub, HashTypeFreeHandles + + VarSetCapacity(read_buf,BUFF_SIZE,0) + + hCryptHashData := DllCall("GetProcAddress", "Ptr", hModule, "AStr", "CryptHashData", "Ptr") + While (cbCount := f.RawRead(read_buf, BUFF_SIZE)) + { + if (cbCount = 0) + break + + if !dllCall(hCryptHashData + ,"Ptr",hHash + ,"Ptr",&read_buf + ,"Uint",cbCount + ,"Uint",0 ) + Gosub, HashTypeFreeHandles + } + + if !dllCall("Advapi32\CryptGetHashParam" + ,"Ptr",hHash + ,"Uint",HP_HASHSIZE + ,"Uint*",HashLen + ,"Uint*",HashLenSize := 4 + ,"UInt",0 ) + Gosub, HashTypeFreeHandles + + VarSetCapacity(pbHash,HashLen,0) + if !dllCall("Advapi32\CryptGetHashParam" + ,"Ptr",hHash + ,"Uint",HP_HASHVAL + ,"Ptr",&pbHash + ,"Uint*",HashLen + ,"UInt",0 ) + Gosub, HashTypeFreeHandles + + SetFormat,integer,Hex + loop,%HashLen% + { + num := numget(pbHash,A_index-1,"UChar") + hashval .= substr((num >> 4),0) . substr((num & 0xf),0) + } + SetFormat,integer,D + +HashTypeFreeHandles: + f.Close() + DllCall("FreeLibrary", "Ptr", hModule) + dllCall("Advapi32\CryptDestroyHash","Ptr",hHash) + dllCall("Advapi32\CryptReleaseContext","Ptr",hCryptProv,"UInt",0) + return hashval +} \ No newline at end of file diff --git a/Launcher/lib/ssdp-i.ahk b/Launcher/lib/ssdp-i.ahk new file mode 100644 index 0000000..a01a22b --- /dev/null +++ b/Launcher/lib/ssdp-i.ahk @@ -0,0 +1,53 @@ +DownloadFile(UrlToFile, SaveFileAs, Overwrite := True, UseProgressBar := True) { + ;Check if the file already exists and if we must not overwrite it + If (!Overwrite && FileExist(SaveFileAs)) + Return + ;Check if the user wants a progressbar + If (UseProgressBar) { + ;Initialize the WinHttpRequest Object + WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1") + ;Download the headers + WebRequest.Open("HEAD", UrlToFile) + WebRequest.Send() + ;Store the header which holds the file size in a variable: + FinalSize := WebRequest.GetResponseHeader("Content-Length") + ;Create the progressbar and the timer + global TheProgressText, TheProgressBar + Gui, Color, FFFFFF + Gui, Font, s11 + Gui, Add, Text, x0 y20 w400 h34 Center vTheProgressText, Establishing server link... + Gui, Add, Progress, x20 y70 w360 h20 vTheProgressBar -Smooth +Theme, 0 + Gui, -MaximizeBox +MinimizeBox -SysMenu -Resize + Gui, Show, w400 h110, Singularity Updater + ;Progress, W400 H110 ZX20 ZY20 WM500 M T, , Establishing server link...`n, Singularity Updater ;%UrlToFile% + SetTimer, __UpdateProgressBar, 100 + } + ;Download the file + UrlDownloadToFile, %UrlToFile%, %SaveFileAs% + ;Remove the timer and the progressbar because the download has finished + If (UseProgressBar) { + Gui, Destroy + ;Progress, Off + SetTimer, __UpdateProgressBar, Off + } + Return + + ;The label that updates the progressbar + __UpdateProgressBar: + ;Get the current filesize and tick + CurrentSize := FileOpen(SaveFileAs, "r").Length ;FileGetSize wouldn't return reliable results + CurrentSizeTick := A_TickCount + ;Calculate the downloadspeed + Speed := Round((CurrentSize/1024-LastSize/1024)/((CurrentSizeTick-LastSizeTick)/1000)) . " Kb/s" + ;Save the current filesize and tick for the next time + LastSizeTick := CurrentSizeTick + LastSize := FileOpen(SaveFileAs, "r").Length + ;Calculate percent done + PercentDone := Round(CurrentSize/FinalSize*100) + ;Update the ProgressBar + GuiControl,, TheProgressText, Downloading patch file at %Speed%`n(%SaveFileAs%) + GuiControl,, TheProgressBar, %PercentDone% + Gui, Show, NA, Singularity Updater (%PercentDone%`%) + ;Progress, %PercentDone%, , Downloading patch file at %Speed%`n(%SaveFileAs%), Singularity Updater (%PercentDone%`%) + Return +} \ No newline at end of file diff --git a/Launcher/lib/ssdp.ahk b/Launcher/lib/ssdp.ahk new file mode 100644 index 0000000..291617f --- /dev/null +++ b/Launcher/lib/ssdp.ahk @@ -0,0 +1,42 @@ +DownloadFile(UrlToFile, SaveFileAs, Overwrite := True, UseProgressBar := True) { + ;Check if the file already exists and if we must not overwrite it + If (!Overwrite && FileExist(SaveFileAs)) + Return + ;Check if the user wants a progressbar + If (UseProgressBar) { + ;Initialize the WinHttpRequest Object + WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1") + ;Download the headers + WebRequest.Open("HEAD", UrlToFile) + WebRequest.Send() + ;Store the header which holds the file size in a variable: + FinalSize := WebRequest.GetResponseHeader("Content-Length") + ;Create the progressbar and the timer + Progress, W400 H110 ZX20 ZY20 WM500 M T, , Downloading...`n, %UrlToFile% + SetTimer, __UpdateProgressBar, 100 + } + ;Download the file + UrlDownloadToFile, %UrlToFile%, %SaveFileAs% + ;Remove the timer and the progressbar because the download has finished + If (UseProgressBar) { + Progress, Off + SetTimer, __UpdateProgressBar, Off + } + Return + + ;The label that updates the progressbar + __UpdateProgressBar: + ;Get the current filesize and tick + CurrentSize := FileOpen(SaveFileAs, "r").Length ;FileGetSize wouldn't return reliable results + CurrentSizeTick := A_TickCount + ;Calculate the downloadspeed + Speed := Round((CurrentSize/1024-LastSize/1024)/((CurrentSizeTick-LastSizeTick)/1000)) . " Kb/s" + ;Save the current filesize and tick for the next time + LastSizeTick := CurrentSizeTick + LastSize := FileOpen(SaveFileAs, "r").Length + ;Calculate percent done + PercentDone := Round(CurrentSize/FinalSize*100) + ;Update the ProgressBar + Progress, %PercentDone%, , Downloading patch file at %Speed%`n(%SaveFileAs%), Singularity Updater (%PercentDone%`%) + Return +} \ No newline at end of file diff --git a/Launcher/realm.ico b/Launcher/realm.ico new file mode 100644 index 0000000..46a954c Binary files /dev/null and b/Launcher/realm.ico differ diff --git a/Launcher/res/RS-Icon-G.png b/Launcher/res/RS-Icon-G.png new file mode 100644 index 0000000..b95a92d Binary files /dev/null and b/Launcher/res/RS-Icon-G.png differ diff --git a/Launcher/res/RS-Title-G.png b/Launcher/res/RS-Title-G.png new file mode 100644 index 0000000..b05db11 Binary files /dev/null and b/Launcher/res/RS-Title-G.png differ diff --git a/Launcher/rs-Launcher.exe b/Launcher/rs-Launcher.exe new file mode 100644 index 0000000..907dfd3 Binary files /dev/null and b/Launcher/rs-Launcher.exe differ diff --git a/Launcher/rs-Updater.exe b/Launcher/rs-Updater.exe new file mode 100644 index 0000000..5ccb7a9 Binary files /dev/null and b/Launcher/rs-Updater.exe differ diff --git a/Launcher/rs-launcher.ahk b/Launcher/rs-launcher.ahk new file mode 100644 index 0000000..b14e245 --- /dev/null +++ b/Launcher/rs-launcher.ahk @@ -0,0 +1,201 @@ +; /* ------------------------------------------------------------ */ +; Script Name : Resistance Saga FYP Launcher +; Version : 1.1.0.1006 +; Author : Yandols Z'eon X +; Supported Platforms : 64-bit Windows platforms. +; /* ------------------------------------------------------------ */ +#SingleInstance Force ; REMEMBER TO CHANGE TO IGNORE BEFORE COMPILING FOR RELEASE +#NoEnv +#NoTrayIcon +;#Warn ; DEBUG ONLY. REMEMBER TO REMOVE/COMMENT OUT THIS LINE BEFORE COMPILING FOR RELEASE +SendMode Input +SetWorkingDir %A_ScriptDir% +AppName=Resistance Saga Launcher +AppVer=1.1.0.1006 +AppAuthor=YandolsZX +AppTitle=%AppName% (Version %AppVer%) +AppDataFolder=%A_AppData%\Locaria Technologies\RSF +ProductName=Resistance Saga +gosub Initialization + +Gui, Add, Pic, x40 y-124 w-1 h600 BackgroundTrans, %A_Temp%\RSFL-Logo.png + +Gui, Font, bold +Gui, Add, Button, x020 y236 w640 h36 vBtnStart gBtnStart Default, &Start Game +Gui, Font, norm +Gui, Add, Button, x020 y280 w200 h36 vBtnNews gBtnNews, &News +Gui, Add, Button, x240 y280 w200 h36 vBtnSettings gBtnSettings, &Options +Gui, Add, Button, x460 y280 w200 h36 vBtnQuit gBtnQuit, &Quit +Gui, Add, StatusBar,, ` Checking for Updates... +SB_SetParts(360, 120) +SB_SetText("A game by " . AppAuthor . " for his FYP.", 3) +Gui, Show, w680 h350, %AppName% +SetTimer, CheckUpdates, 300 +GuiControl, Disable, BtnStart + +;GuiControl,, BtnStart, Checking for Updates... +;sleep 3000 +;GuiControl,, BtnStart, &Start Game +;GuiControl, Enable, BtnStart +;GuiControl, Focus, BtnStart +Return + +BtnStart: +Gui, Submit +RunWait, win64\rsaga.exe,, UseErrorLevel +If ErrorLevel +{ + Msgbox, 16, %AppName%, Failed to start the game. Please make sure the game is up to date and you have DirectX 10 installed. `n`nIf you think your installation is corrupted, use the 'Redownload Game Data' option in settings. + ExitApp, 13 +} +Else + ExitApp +Return + +BtnNews: +Run, https://yandols.xyz/resistance-saga,, UseErrorLevel +If ErrorLevel + MsgBox, 0, %AppName%, A reserved action failed to process. +Return + +BtnSettings: +SetTimer, CheckUpdates, Off +Gui, Hide +Gui, 2:-MaximizeBox -MinimizeBox +Gui, 2:Add, GroupBox, x10 y10 w240 h90, Versions +Gui, 2:Add, Text, x20 y30, Launcher Version : %AppVer% +Gui, 2:Add, Text, x20 y50, Game Version : %ProductVer% +Gui, 2:Add, Text, x20 y70, Last Hash : %RSLastHash% +Gui, 2:Add, GroupBox, x10 y110 w240 h120, Tools: +Gui, 2:Add, Button, x20 y130 w220 h26 gBtnRedownload, Redownload &Game Data +Gui, 2:Add, Button, x20 y160 w220 h26 gBtnDirectX, (Re)install &DirectX +Gui, 2:Add, Button, x20 y190 w220 h26 gBtnClearData, &Clear Persistent User Data +Gui, 2:Add, Button, x20 y240 w220 h26 g2GuiClose Default, < &Back +Gui, 2:Show, w260 h280, %AppName% Settings +Return + +BtnRedownload: +Gui, +OwnDialogs +If IsDownloadingFromScratch = 1 + Goto RedownloadGameData + +MsgBox, 52, Redownload Game Data, This will redownload the latest version of the game from the server. Normally used if there is something wrong with your installation of the game. Proceed? +IfMsgBox, Yes + Goto, RedownloadGameData +Else + Return +Return + +RedownloadGameData: +RunWait, rs-updater.exe /forceupdate,, UseErrorLevel +If ErrorLevel +{ + Msgbox, 16, Fatal Error, Updater failed to start because the component is missing. + ExitApp, 18 +} +ExitApp +Return + +BtnDirectX: +Gui, +OwnDialogs +RunWait, win64\dxwebsetup.exe,, UseErrorLevel +If ErrorLevel +{ + Msgbox, 16, Fatal Error, Setup failed to start because the component is missing. + ExitApp, 17 +} +Return + +BtnClearData: +Gui, +OwnDialogs +Msgbox, 52, Clear Presistent User Data, This will delete all of the game's persistent user data and cache that is stored in your AppData. The game files and any save data are left intact and must be removed manually. +IfMsgBox, Yes +{ + Gui, Hide + ; -- Disabled because not currently working for some reason -- + ;FileDelete, %A_AppData%\ResistanceSaga\*.* + ;FileDelete, %A_AppData%\ResistanceSagaFYP\*.* + ;FileRemoveDir, %A_AppData%\ResistanceSaga, 1 + ;FileRemoveDir, %A_AppData%\ResistanceSagaFYP, 1 + Msgbox, 16, Clear Persistent User Data, Operation failed. Something went wrong, the launcher was unable to clear any of the persistent user data. `n`nTo manually clear the user data, go to your Local AppData folder and delete the 'ResistanceSaga' and 'ResistanceSagaFYP' folders. + ;Msgbox, 64, Clear Persistent User Data, User Data and Cache successfully deleted. + Reload + Return +} +IfMsgBox, No + Return +Return + + +2GuiEscape: +2GuiClose: +Gui, 2:Destroy +Gui, 1:Show +Return + +CheckUpdates: +Thread, interrupt, 0 +SetTimer, CheckUpdates, Off +/* -- DEPRECATED -- +If NoUpdaterPrompt = true + return +*/ +UrlDownloadToFile, https://kin.yandols.xyz/rs-fyp.ini, %A_Temp%/csu-resistancesaga-1.vc +If ErrorLevel +{ + SB_SetText(" Unable to connect to patch server.", 1) + return +} +;; Read Remote Config +IniRead, CSU_NewVersion, %A_Temp%/csu-resistancesaga-1.vc, SingularityUpdater, VersionToUse, 0 +IniRead, CSU_Identifier, %A_Temp%/csu-resistancesaga-1.vc, SingularityUpdater, Identifier, null +If CSU_Identifier = RESISTANCESAGA-FYP +{ + If CSU_NewVersion != %ProductVer% + { + SB_SetText(" A new update has been found. (" . CSU_NewVersion . ")", 1) + SB_SetText(" Your Ver: " . ProductVer, 2) + Run, rs-updater.exe, %A_ScriptDir%, UseErrorLevel + If ErrorLevel + Msgbox, 16, Fatal Error, Updater failed to start because the component is missing. + } + Else + { + SB_SetText(" No updates found.", 1) + SB_SetText(" Your Ver: " . ProductVer, 2) + } +} +GuiControl, Enable, BtnStart +GuiControl, Focus, BtnStart +return +return + + +Initialization: +FileInstall, res\RS-Icon-G.png, %A_Temp%\RSFL-Icon.png, 1 +FileInstall, res\RS-Title-G.png, %A_Temp%\RSFL-Logo.png, 1 +FileRead, ProductVer, win64\rversion.txt +FileRead, RSLastHash, win64\rhash.txt + +IfNotExist, rs-Updater.exe + FileInstall, rs-Updater.exe, rs-Updater.exe, 0 + +IfNotExist, win64 +{ + Msgbox, 4, %AppName%, Game data could not be found. Download now? (It will be installed in the directory where the launcher is.) + IfMsgBox, Yes + { + IsDownloadingFromScratch = 1 + Goto BtnRedownload + } + Else + Return +} + +Return + +BtnQuit: +GuiEscape: +GuiClose: +ExitApp +Return diff --git a/Launcher/rs-launcher.ahk.ini b/Launcher/rs-launcher.ahk.ini new file mode 100644 index 0000000..16a70e4 Binary files /dev/null and b/Launcher/rs-launcher.ahk.ini differ diff --git a/Launcher/rs-launcher.ahk_1.ico b/Launcher/rs-launcher.ahk_1.ico new file mode 100644 index 0000000..acaf941 Binary files /dev/null and b/Launcher/rs-launcher.ahk_1.ico differ diff --git a/Launcher/rs-updater.ahk b/Launcher/rs-updater.ahk new file mode 100644 index 0000000..55eced6 --- /dev/null +++ b/Launcher/rs-updater.ahk @@ -0,0 +1,372 @@ +; /* ------------------------------------------------------------ */ +; Script Name : Singularity Updater (For Resistance Saga) +; Version : 3.0.4.5142 +; Author : Yandols Z'eon X +; Supported Platforms : Any 64-bit system +; /* ------------------------------------------------------------ */ +#Include lib\ssdp-i.ahk +#Include lib\hashvalidate.ahk +#SingleInstance Ignore +#NoEnv +#NoTrayIcon +; #Warn ;-- Enable to display some debug information. +SendMode Input +SetWorkingDir %A_ScriptDir% +;; ---------------------------------- +;; Configuration Section -- Start +ProductName = Resistance Saga +ProductProcessName = rs-Launcher.exe +AppName = Singularity Updater +AppAuth = Yandols Zeon X +UpdaterInternalName = Singularity Updater +UpdaterInternalVersion = 3.0.4.5142 +UpdaterProcessName = rs-Updater.exe +UpdaterHost = https://kin.yandols.xyz +UpdaterRemoteConfig = rs-fyp.ini +UpdaterServerKeyprint = f3e371ec28b221c0ff46b45f44e1e647 +CacheDir = %A_Temp% +CachedPatchName = rs-gameupdate-package.vi +ConfigFileName = csu-resistancesaga-2.vs +AliasFileName = csu-multiupdate0.vs +LauncherAlias = CSU_ +VersionAlias = 3045141_ +;; Configuration Section -- End +;; Anything beyond this line should only need to be changed whenever things like libraries are updated and parameters need to be recoded. + +;; ---------------------------------- +;; De-instancer for after program self-updating is completed. +IfExist, %A_ScriptDir%\%LauncherAlias%_patchrstats.vs +{ + goto PostUpdateCompletion + return +} +;; De-instancer (Compatibility Fix for updating from Pre-3.0.4 updater). +IfExist, %A_ScriptDir%\PatchrCompletionNotice.vs +{ + CompatibilityFixMode = 1 + goto PostUpdateCompletion + return +} + +;; ---------------------------------- +;; Instance the updater in cache folder to allow self-updating of the updater. +If A_IsCompiled = 1 +{ + If A_ScriptName != %LauncherAlias%%VersionAlias%%UpdaterProcessName% + { + ;Msgbox, 0, Debug Notice, Running in local directory + FileCopy, %UpdaterProcessName%, %A_Temp%\%LauncherAlias%%VersionAlias%%UpdaterProcessName%, 1 + FileDelete, %A_Temp%\%LauncherAlias%%VersionAlias%%AliasFileName% + FileAppend, %A_ScriptDir%, %A_Temp%\%LauncherAlias%%VersionAlias%%AliasFileName% + FileInstall, lib\UnFurl3.exe, %A_Temp%\FurlPatcher.exe, 1 + Run, %A_Temp%\%LauncherAlias%%VersionAlias%%UpdaterProcessName% %1%, %A_ScriptDir%, UseErrorLevel + If ErrorLevel + ExitApp + ExitApp + } + If A_ScriptName = %LauncherAlias%%VersionAlias%%UpdaterProcessName% + { + ;Msgbox, 0, Debug Notice, Running in alias directory + FileRead, AliasWorkingDir, %LauncherAlias%%VersionAlias%%AliasFileName% + + } +} +;; Added testing environment compatibility to speed up uncompiled testing +Else If A_IsCompiled != 1 +{ + ;Msgbox, 0, Debug Notice, Running in local directory (uncompiled) + ;FileDelete, %A_Temp%\%LauncherAlias%%VersionAlias%%AliasFileName% + ;FileAppend, %A_ScriptDir%, %A_Temp%\%LauncherAlias%%VersionAlias%%AliasFileName% + ;FileRead, AliasWorkingDir, %LauncherAlias%%VersionAlias%%AliasFileName% + AliasWorkingDir = %A_ScriptDir% +} + +;; ---------------------------------- +;; Check if /forceupdate paramter is passed. +If 1 = /forceupdate + goto ForceUpdate + +;; ---------------------------------- +;; Normal operations - Update Prompt + +gosub ReadPatchFile + +If ExtUpdateNotice = true +{ + If ReleaseDate != null + NewUpdateMessage = An update for %ProductName% is available`, would you like to download the new update? `n`nThe latest version is %VersionToUse%, released %ReleaseDate% + else + NewUpdateMessage = An update for %ProductName% is available`, would you like to download the new update? `n`nThe latest version is %VersionToUse% +} +else + NewUpdateMessage = An update for %ProductName% is available`, would you like to download the new update? + +Msgbox, 68, %AppName%, %NewUpdateMessage% +IfMsgbox, Yes + goto TaskUpdater +else + ExitApp +return +return + +;; ---------------------------------- +;; Commence Downloader and Patcher Subroutines +TaskUpdater: +Process, Close, %ProductProcessName% ; Specific to RS only. Remove line here for other apps. +If DownloadType = SingleFile + ThePatchFile = %UpdaterHost%/%File% +Else If DownloadType = URL + ThePatchFile = %URL% +Else + ThePatchFile = %UpdaterHost%/%File% +DownloadFile(ThePatchFile, CachedPatchName, True, True) +sleep 500 ; Prevents thread overload +Gui, Destroy ; Redundancy Backup +Progress, Off ; Redundancy Backup +fileToValidate := CachedPatchName +LocalPatchHash := HashFile(fileToValidate,2) +If LocalPatchHash != %FileHash% + goto PatchValidationFailed +sleep 250 ; Prevents thread overload +Gui, Destroy ; Redundancy Backup +Progress, Off ; Redundancy Backup +;Msgbox, 4, %AppName%, Patch file successfully downloaded`, install now? ;`n`nLocal Hash: %LocalPatchHash%`nRemote Hash: %FileHash% +Msgbox, 0, %AppName%, Patch file successfully downloaded. Installation will now proceed. , 3 + +;; ---------------------------------- +;; Handles Installing the downloaded patch. +;; Added in 5142 and removed Yes or No prompt since pressing No will always make the patch redownload again anyways. +TaskInstallPatch: +sleep 500 ; Prevents thread overload +Process, Close, %ProductProcessName% +sleep 100 ; Prevents thread overload +IfExist, patched.log + FileDelete, patched.log +IfExist, patcherbat.bat + FileDelete, patcherbat.bat +FileInstall, lib\UnFurl3.exe, FurlPatcher.exe, 1 +FileAppend, FurlPatcher.exe x -y "%CachedPatchName%" "%AliasWorkingDir%" >patched.log, patcherbat.bat +FileSetAttrib, +R+H+S, FurlPatcher.exe +FileSetAttrib, +R+H+S, patcherbat.bat +RunWait, patcherbat.bat,, Hide UseErrorLevel +;RunWait, FurlPatcher.exe x -y "%CachedPatchName%" >patched.log,, UseErrorLevel +If ErrorLevel +{ + If ErrorLevel = 2 + Msgbox, 16, %AppName%, A fatal error has occured. Try rebooting your computer and try again.`n[Error Code: %ErrorLevel%] + Else If ErrorLevel = 3 + Msgbox, 16, %AppName%, Patching has failed due to invalid checksum, the internal data is damaged. Open the file "patched.log" in a text editor before starting the updater again for error information.`n[Error Code: %ErrorLevel%] + Else If ErrorLevel = 6 + Msgbox, 16, %AppName%, Patching has failed due to one or more required files are locked by other processes such as anti-virus software. Open the file "patched.log" in a text editor before starting the updater again for error information.`n[Error Code: %ErrorLevel%] + Else If ErrorLevel = 7 + Msgbox, 16, %AppName%, Patching has failed. Open the file "patched.log" in a text editor before starting the updater again for error information.`n[Error Code: %ErrorLevel%] + Else If ErrorLevel = 8 + Msgbox, 16, %AppName%, A memory leak has been detected, patching has been aborted. Please reboot your computer and try again.`n[Error Code: %ErrorLevel%] + Else If ErrorLevel = 9 + Msgbox, 16, %AppName%, Patching has failed partially. The updater was not able to instance itself and is most likely not able to replace one or more needed files. Try running the updater again with administrator privileges.`n[Error Code: %ErrorLevel%] + Else If ErrorLevel = 10 + Msgbox, 16, %AppName%, Patching has failed. The downloaded patch file seems to have disappeared. Try running the updater again with administrator privileges.`n[Error Code: %ErrorLevel%] + Else If ErrorLevel = 11 + Msgbox, 16, %AppName%, Patching has failed. The downloaded patch file is not a %ProductName% patch. Please contact the author to have this fixed asap.`n[Error Code: %ErrorLevel%] + Else + Msgbox, 16, %AppName%, Patching has failed. Open the file "patched.log" in a text editor before starting the updater again for error information.`n[Error Code: %ErrorLevel%] + DontDeleteLogFile = 1 + PatchHasFailed = 1 +} +sleep 100 ; Prevents thread overload +FileSetAttrib, -R-S, FurlPatcher.exe +FileSetAttrib, -R-S, patcherbat.bat +FileDelete, FurlPatcher.exe +FileDelete, patcherbat.bat +FileDelete, %CachedPatchName% +If DontDeleteLogFile != 1 + FileDelete, patched.log + +If PatchHasFailed = 1 + ExitApp + +FileAppend, STATUS_COMPLETED, %AliasWorkingDir%\%LauncherAlias%_patchrstats.vs +FileSetAttrib, +H+S, %LauncherAlias%_patchrstats.vs +sleep 150 ; Prevents thread overload +Run, %AliasWorkingDir%\%UpdaterProcessName%,, UseErrorLevel +If ErrorLevel +{ + Msgbox, 16, %AppName%, Failed to switch instances. This may be caused by an invalid or failed update attempt. + ExitApp +} +; ;If PatchHasFailed != 1 +; ;Msgbox, 64, %AppName%, Patching completed. You are now running on the latest version of %ProductName%! + +ExitApp +return + +;; ---------------------------------- +;; Error handling when downloaded patch file's hash does not match remote hash file +PatchValidationFailed: +sleep 100 ; Prevents thread overload +Msgbox, 16, %AppName%, Warning: Patch file validation has failed! The file that was downloaded may be corrupted, please try running the updater again. If problem persists, please contact the author to have this fixed asap. +ExitApp +return + +;; ---------------------------------- +;; De-instancing handler and post update completion notice. +PostUpdateCompletion: +If CompatibilityFixMode = 1 +{ + ;IniRead, VersionToUse, %CacheDir%/clayupdate-rmtclock.vc, SingularityUpdater, VersionToUse, null + FileSetAttrib, -R+H+S, PatchrCompletionNotice.vs + sleep 100 ; Prevents thread overload +} +IniRead, VersionToUse, %CacheDir%/%ConfigFileName%, SingularityUpdater, VersionToUse, null +FileSetAttrib, -R+H+S, %LauncherAlias%_patchrstats.vs +sleep 100 ; Prevents thread overload +Msgbox, 64, %AppName%, Patching completed. Your version of %ProductName% has been updated to version %VersionToUse%! +FileSetAttrib, -R-S, FurlPatcher.exe +FileSetAttrib, -R-S, patcherbat.bat +FileDelete, FurlPatcher.exe +FileDelete, patcherbat.bat +FileDelete, %CachedPatchName% +FileDelete, %AliasFileName% +FileDelete, %LauncherAlias%_patchrstats.vs +If DontDeleteLogFile != 1 + FileDelete, patched.log +FileDelete, %LauncherAlias%%VersionAlias%%AliasFileName% +FileDelete, %LauncherAlias%%VersionAlias%%UpdaterProcessName% +If CompatibilityFixMode = 1 +{ + FileDelete, %CachedPatchName% + FileDelete, %AliasFileName% + FileDelete, PatchrCmd.vs + FileDelete, PatchrCompletionNotice.vs + FileDelete, %LauncherAlias%%VersionAlias%PatchrCmd.vs + FileDelete, %LauncherAlias%%VersionAlias%teal-updater.exe +} +Run, %A_ScriptDir%\%ProductProcessName%, UseErrorLevel +ExitApp +return + +;; ---------------------------------- +;; Force Update Handler (Specific to RS only but may be adapted into main SU) +ForceUpdate: +IsForceUpdating = 1 + +If A_IsCompiled = 1 +{ + If A_ScriptName != %LauncherAlias%%VersionAlias%%UpdaterProcessName% + { + ; Running in local directory + FileCopy, %UpdaterProcessName%, %A_Temp%\%LauncherAlias%%VersionAlias%%UpdaterProcessName%, 1 + FileDelete, %A_Temp%\%LauncherAlias%%VersionAlias%%AliasFileName% + FileAppend, %A_ScriptDir%, %A_Temp%\%LauncherAlias%%VersionAlias%%AliasFileName% + FileInstall, lib\UnFurl3.exe, %A_Temp%\FurlPatcher.exe, 1 + Run, %A_Temp%\%LauncherAlias%%VersionAlias%%UpdaterProcessName%, %A_ScriptDir%, UseErrorLevel + If ErrorLevel + ExitApp + ExitApp + } + If A_ScriptName = %LauncherAlias%%VersionAlias%%UpdaterProcessName% + { + ; Running in alias directory + FileRead, AliasWorkingDir, %LauncherAlias%%VersionAlias%%AliasFileName% + + } +} +;; Added testing environment compatibility to speed up uncompiled testing +Else If A_IsCompiled != 1 + AliasWorkingDir = %A_ScriptDir% + +gosub ReadPatchFile +goto TaskUpdater +Return + + +;; ---------------------------------- +;; Read the patch info downloaded from the remote config file +ReadPatchFile: +;; Always force redownload the remote config file +IfExist, %CacheDir%/%ConfigFileName% + FileDelete, %CacheDir%/%ConfigFileName% +UrlDownloadToFile, %UpdaterHost%/%UpdaterRemoteConfig%, %CacheDir%/%ConfigFileName% + +;; Read Remote Config File +IniRead, RetailVersion, %CacheDir%/%ConfigFileName%, SingularityUpdater, RetailVersion, null +IniRead, VersionToUse, %CacheDir%/%ConfigFileName%, SingularityUpdater, VersionToUse, null +IniRead, ReleaseDate, %CacheDir%/%ConfigFileName%, SingularityUpdater, ReleaseDate, null +IniRead, ExtUpdateNotice, %CacheDir%/%ConfigFileName%, SingularityUpdater, ExtUpdateNotice, false +IniRead, OCVersion, %CacheDir%/%ConfigFileName%, SingularityUpdater, OCVersion, 0 +IniRead, Identifier, %CacheDir%/%ConfigFileName%, SingularityUpdater, Identifier, 0 +IniRead, Keyprint, %CacheDir%/%ConfigFileName%, SingularityUpdater, Keyprint, 0 +IniRead, Optimization, %CacheDir%/%ConfigFileName%, SingularityUpdater, Optimization, null +IniRead, DownloadType, %CacheDir%/%ConfigFileName%, SingularityUpdater, DownloadType, SingleFile +IniRead, File, %CacheDir%/%ConfigFileName%, SingularityUpdater, File, null +IniRead, URL, %CacheDir%/%ConfigFileName%, SingularityUpdater, URL, null +IniRead, FileHash, %CacheDir%/%ConfigFileName%, SingularityUpdater, FileHash, 0 + +;; Make sure the remote config file is the correct one by validating keyprint. +If Keyprint != %UpdaterServerKeyprint% +{ + Msgbox, 16, %AppName%, Patch server authentication failed. + ExitApp +} + +;; Make Forced Updating stop the thread here so that the prompts don't show up. +If IsForceUpdating = 1 +{ + If A_ScriptName != %LauncherAlias%%VersionAlias%%UpdaterProcessName% + { + FileDelete, %A_Temp%\%LauncherAlias%%VersionAlias%%AliasFileName% + FileAppend, %A_ScriptDir%, %A_Temp%\%LauncherAlias%%VersionAlias%%AliasFileName% + Return + } + Return +} + +;; Do not prompt a download if existing version is the same as latest [Compiled Version] +If A_IsCompiled = 1 +{ + If A_ScriptName != %LauncherAlias%%VersionAlias%%UpdaterProcessName% + { + ;Msgbox, 0, Debug Notice, Running in local directory + FileDelete, %A_Temp%\%LauncherAlias%%VersionAlias%%AliasFileName% + FileAppend, %A_ScriptDir%, %A_Temp%\%LauncherAlias%%VersionAlias%%AliasFileName% + ;FileGetVersion, ExistingVersion, %ProductProcessName% + FileRead, ExistingVersion, win64\rversion.txt + If ExistingVersion = %VersionToUse% + { + Msgbox, 64, %AppName%, You already have the latest version currently available. + ExitApp + } + return + } + If A_ScriptName = %LauncherAlias%%VersionAlias%%UpdaterProcessName% + { + ;Msgbox, 0, Debug Notice, Running in alias directory + FileRead, AliasWorkingDir, %LauncherAlias%%VersionAlias%%AliasFileName% + ;FileGetVersion, ExistingVersion, %AliasWorkingDir%\%ProductProcessName% + FileRead, ExistingVersion, %AliasWorkingDir%\win64\rversion.txt + If CSU_NewVersion != %ProductVer% + If ExistingVersion = %VersionToUse% + { + Msgbox, 64, %AppName%, You already have the latest version currently available. + ExitApp + } + return + } +} + + +;; Do not prompt a download if existing version is the same as latest [Uncompiled Version] +;FileGetVersion, ExistingVersion, %ProductProcessName% +FileRead, ExistingVersion, win64\rversion.txt +If ExistingVersion = %VersionToUse% +{ + Msgbox, 64, %AppName%, You already have the latest version currently available. + ExitApp +} +return + +;; ---------------------------------- +;; Nullify Progress Window Standard Closure Calls +GuiClose: +GuiExit: +return diff --git a/Launcher/rs-updater.ahk.ini b/Launcher/rs-updater.ahk.ini new file mode 100644 index 0000000..5d64091 Binary files /dev/null and b/Launcher/rs-updater.ahk.ini differ