This repository has been archived by the owner on Apr 26, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
wb.au3
384 lines (281 loc) · 13 KB
/
wb.au3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
; Wonder Boy: The Dragon's Trap Mod Launcher
; Version 1.0
;
; Copyright 2018 Mateus B. Cassiano
; Licensed under GPLv2+
; Refer to the license.txt file included.
; OVERVIEW / USAGE
; Compile this script with AutoIt v3 and place a copy of the binary inside exe32 and exe64 folders
; found in the install location of Wonder Boy: The Dragon's Trap. The original game binaries must
; be renamed to "wb.bkp.exe" (can be changed through a global variable defined below) and the
; compiled binary of this script must be renamed to "wb.exe".
;
; This mod launcher works only with the Steam or GOG editions of the game. It works by swapping the
; original "bin_pc" folder on the fly before launching the game if a different data directory is
; specified through the command line parameter --data-dir=<folder_name> (e.g. bin_pc_monica). The
; specified data directory must exist next to the original "bin_pc" folder, must not contain spaces
; on its name and must not be named "bin_pc.bkp". Once the game is closed, the original folder
; names and the original "bin_pc" folder are restored to their previous state.
;
; This launcher keeps track of the original folder name through a persistent file stored inside
; the selected data folder, so, in the case of an unexpected crash or system issue, it'll take care
; of this inconsistent state automagically the next time next time it's executed. If no --data-dir
; parameter is passed, it'll just run the game with their original data directly. Any other command
; line parameter specified other than --data-dir=<folder_name> will be forwarded to the original
; game executable.
#NoTrayIcon
#include <MsgBoxConstants.au3>
#Region
#AutoIt3Wrapper_Icon=wb.ico
#AutoIt3Wrapper_Compile_Both=y
#AutoIt3Wrapper_Res_Description=Wonder Boy: The Dragon's Trap Mod Launcher
#AutoIt3Wrapper_Res_Comment=Switch Wonder Boy: The Dragon's Trap resources folder on-the-fly through command line parameter --data-dir=<res_folder>
#AutoIt3Wrapper_Res_LegalCopyright=© 2018 Mateus B. Cassiano. All Rights Reserved.
#AutoIt3Wrapper_res_requestedExecutionLevel=asInvoker
#AutoIt3Wrapper_Res_ProductVersion=1.0.0.0
#AutoIt3Wrapper_Res_Fileversion=1.0.0.0
#AutoIt3Wrapper_Res_Language=1033
#AutoIt3Wrapper_Res_HiDpi=y
#EndRegion
;------------------
; Global Variables
;------------------
Global Const $g_sExeName = "wb.bkp.exe"
Global Const $g_sFullName = "Wonder Boy: The Dragon's Trap Mod Launcher"
; DO NOT remove "bin_pc.bkp" from the array, as it will break the back-up/restore functions.
Global Const $g_asReservedDirNames[4] = ["bin_pc.bkp", "exe32", "exe64", "_CommonRedist"]
Main()
;======
; Main
;------
; Start the launcher
Func Main()
; $asLaunchData[0] store the passed data directory's name (or empty if not provided)
; $asLaunchData[1] store the original command line without --data-dir parameter
Local $asLaunchData = ParseCmdLine($CmdLineRaw)
; Detect game edition and launch
Switch DetectGameEdition()
Case -1 ; Original executable wrongly named or not found
ShowMessage(1)
Exit 1
Case 0 ; Game is Steam Edition
; Check and restore folder names if necessary (but preserve "selected_dir.id")
RestoreDataDir(True)
LaunchSteamEdition($asLaunchData)
Case 1 ; Game is GOG Edition
; Check and restore folder names if necessary (but preserve "selected_dir.id")
RestoreDataDir(True)
LaunchGOGEdition($asLaunchData)
Case Else ; Game edition not recognized
ShowMessage(2)
Exit 1
EndSwitch
Exit 0
EndFunc ;==>Main
;==============
; ParseCmdLine
;--------------
; Read --data-dir parameter from $sCmdLine (if present) and returns the value of
; it and the original command line without --data-dir parameter in an array
Func ParseCmdLine(Const ByRef $sCmdLine)
Local $asResult[2]
; Try to find --data-dir=<folder_name> in the Command Line. If found, use RegExp to filter
; this parameter from the command line, otherwise just return the original command line
$RegexResult = StringRegExp($sCmdLine, "\-\-data\-dir\=(\S+)", 1)
If @error == 0 Then
; Data directory was specified, store it in the first position of the array
; and the filtered command line in the second position of the array
$asResult[0] = $RegexResult[0]
$asResult[1] = StringRegExpReplace($sCmdLine, "(.*)\-\-data\-dir\=\S+\s?(.*)", "$1$2")
Else
; Data directory wasn't specified, store an empty string in the first position of the array
; and the original and untouched command line in the second position of the array
$asResult[0] = ""
$asResult[1] = $sCmdLine
EndIf
Return $asResult
EndFunc ;==>ParseCmdLine
;===================
; DetectGameEdition
;-------------------
; Checks the files inside the folder the launcher is placed and determine game edition
Func DetectGameEdition()
Local $iResult
; Check if GOG Galaxy DLLs are present. If yes, it's the GOG Edition
If FileExists(".\Galaxy.dll") Or FileExists(".\Galaxy64.dll") Then
$iResult = 1
; Check if Steam API DLLs are present. If yes, it's the Steam Edition. This check MUST be done
; only AFTER cheking the GOG Galaxy DLLs because the GOG Edition also ships with the Steam DLLs
ElseIf FileExists(".\steam_api.dll") Or FileExists(".\steam_api64.dll") Then
$iResult = 0
EndIf
; Original game executable not found or wrongly named. This check MUST be done AFTER the others
; so it takes precedence, after all, without the original executable the game simply can't run
If Not FileExists(".\" & $g_sExeName) Then
$iResult = -1
EndIf
Return $iResult
EndFunc ;==>DetectGameEdition
;================
; IsDataDirValid
;----------------
; Check if the directory specified in $sDataDir exists and doesn't correspond to a reserved folder
; Also checks if the backup folder couldn't be automatically restored and exits if that's the case
Func IsDataDirValid(Const ByRef $sDataDir)
Local $bResult
; RestoreDataDir() should be called at least once before calling IsDataDirValid() and should
; automatically rename the backup folder to its previous name. If despite this the backup
; folder is still there, something really wrong happened, throw error and exit
If DirGetSize("..\bin_pc.bkp") <> -1 Then
ShowMessage(3)
; Call RestoreDataDir() once more to ensure "selected_dir.id" is deleted before exiting
RestoreDataDir(False)
Exit 1
EndIf
; Check if the specified directory exists. If it doesn't, warn the user and call
; RestoreDataDir(False) to ensure "selected_dir.id" is deleted before continuing
If $sDataDir <> "" And DirGetSize("..\" & $sDataDir) <> -1 Then
$bResult = True
ElseIf $sDataDir <> "" Then
ShowMessage(4, $sDataDir)
RestoreDataDir()
$bResult = False
Else
$bResult = False
EndIf
; Check if the specified directory doesn't match a reserved directory. If it does, warn the
; user and call RestoreDataDir(False) to ensure "selected_dir.id" is deleted before continuing
For $i = 0 To UBound($g_asReservedDirNames) - 1
If $g_asReservedDirNames[$i] == $sDataDir Then
ShowMessage(5, $sDataDir)
RestoreDataDir()
$bResult = False
EndIf
Next
Return $bResult
EndFunc ;==>IsDataDirValid
;================
; PrepareDataDir
;----------------
; Renames the original "bin_pc" folder to "bin_pc.bkp" then assign this name to the selected data
; directory. Also saves the original folder name of the selected data directory in a hidden file
; so everything can be properly restored to the previous state by calling RestoreDataDir() later
Func PrepareDataDir(Const ByRef $sDataDir)
; If the selected data directory is "bin_pc", there's nothing to do, just return
If $sDataDir == "bin_pc" Then
Return
EndIf
; If "bin_pc" already exists, rename it to "bin_pc.bkp"
If DirGetSize("..\bin_pc") <> -1 Then
DirMove("..\bin_pc", "..\bin_pc.bkp")
EndIf
; Rename the selected data directory to "bin_pc" and save its original name in a hidden file
DirMove("..\" & $sDataDir, "..\bin_pc")
FileWrite("..\bin_pc\data_dir.id", $sDataDir & @CRLF)
FileSetAttrib("..\bin_pc\data_dir.id", "+SH")
Return
EndFunc ;==>PrepareDataDir
;================
; RestoreDataDir
;----------------
; Restores the original name of the last selected data directory then renames "bin_pc.bkp" back
; to "bin_pc". The optional parameter controls whether "selected_dir.id" should also be deleted
Func RestoreDataDir(Const $bKeepSelectedDirID = False)
; Check if the original name of the last selected data directory is available
If FileExists("..\bin_pc\data_dir.id") Then
; Read original folder name from the hidden file then delete it
Local $sDataDir = FileReadLine("..\bin_pc\data_dir.id")
FileSetAttrib("..\bin_pc\data_dir.id", "-SH")
FileDelete("..\bin_pc\data_dir.id")
; Rename "bin_pc" to its original folder name
DirMove("..\bin_pc", "..\" & $sDataDir)
; If "bin_pc.bkp" exists, rename it back to "bin_pc"
If DirGetSize("..\bin_pc.bkp") <> -1 Then
DirMove("..\bin_pc.bkp", "..\bin_pc")
EndIf
EndIf
; Delete "selected_dir.id" if $bKeepSelectedDirID wasn't set to True when calling this function
If Not $bKeepSelectedDirID Then
FileSetAttrib("..\selected_dir.id", "-SH")
FileDelete("..\selected_dir.id")
EndIf
Return
EndFunc ;==>RestoreDataDir
;====================
; LaunchSteamEdition
;--------------------
; Validate and prepare the specified data directory then launch the original Steam game executable
Func LaunchSteamEdition(ByRef $asLaunchData)
; Create a hidden "selected_dir.id" file or open existing file and seek to initial position,
; then (over)write the selected data directory name on it and close the file
Local $hFileHandle = FileOpen("..\selected_dir.id", 2)
FileWrite($hFileHandle, $asLaunchData[0] & @CRLF)
FileClose($hFileHandle)
FileSetAttrib("..\selected_dir.id", "+SH")
; Check through registry if the Steam Client is reporting the game is running. If it's not,
; Steam will likely relaunch this executable again (e.g. Steam was not running, the game was
; started by another process or shortcut, etc), so just pass ahead the filtered command line
If RegRead("HKCU\Software\Valve\Steam\Apps\543260", "Running") == 1 Then
; Retrieve the selected data directory from the hidden file. This instance isn't guaranteed
; to be the first (e.g. Steam Client likely relaunched this executable) so the --data-dir
; parameter won't be available anymore because it was filtered by the first instace
$asLaunchData[0] = FileReadLine("..\selected_dir.id")
; Check if the specified data directory is valid and prepare it for the game
If IsDataDirValid($asLaunchData[0]) Then
PrepareDataDir($asLaunchData[0])
EndIf
; Finally, launch the original game executable with the filtered command line and wait
; until it exits. Then, restore the original folder names and delete "selected_dir.id"
RunWait($g_sExeName & " " & $asLaunchData[1])
RestoreDataDir(False)
Else
; If we got there, Steam will relaunch this executable again.
; Don't do anything, just forwards the filtered command line.
RunWait($g_sExeName & " " & $asLaunchData[1])
EndIf
Return
EndFunc ;==>LaunchSteamEdition
;==================
; LaunchGOGEdition
;------------------
; Validate and prepare the specified data directory then launch the original GOG game executable
Func LaunchGOGEdition(Const ByRef $asLaunchData)
; Check if the specified data directory is valid and prepare it for the game
If IsDataDirValid($asLaunchData[0]) Then
PrepareDataDir($asLaunchData[0])
EndIf
; Launch the original game executable with the filtered command line and wait until it exits.
; Then, restore the original folder names and delete "selected_dir.id" if it exists
RunWait($g_sExeName & " " & $asLaunchData[1])
RestoreDataDir(False)
Return
EndFunc ;==>LaunchGOGEdition
;=============
; ShowMessage
;-------------
; Display Message Boxes with predetermined error/warning messages and in some cases extra info
Func ShowMessage(Const $iMsgCode, Const $sMsgExtra = "")
; Determine from $iMsgCode
Switch $iMsgCode
Case 1 ; Original executable wrongly named or not found
MsgBox($MB_ICONERROR, $g_sFullName, "Couldn't find the original game executable [" _
& $g_sExeName & "]." & @CRLF & "Please make sure this launcher is placed on" _
& " the correct game folder, then try again.")
Case 2 ; Unknown game edition
MsgBox($MB_ICONERROR, $g_sFullName, "Couldn't determine the game edition." & @CRLF _
& "This launcher supports only the GOG and Steam editions.")
Case 3 ; Inconsistent game folders (failed to recover automatically)
MsgBox($MB_ICONERROR, $g_sFullName, "Couldn't restore the backup folder " _
& "automatically." & @CRLF & "Please check the contents of the install " _
& "folder, then try again.")
Case 4 ; Selected data directory doesn't exist / couldn't be accessed
MsgBox($MB_ICONWARNING, $g_sFullName, "The specified data directory [" & $sMsgExtra _
& "] doesn't exist." & @CRLF & "Launching the game with the default data " _
& "directory.")
Case 5 ; Selected data directory name is reserved
MsgBox($MB_ICONWARNING, $g_sFullName, "The specified data directory [" & $sMsgExtra _
& "] is reserved and can't be used." & @CRLF & "Launching the game with the" _
& " default data directory.")
EndSwitch
Return
EndFunc ;==>ShowMessage