Skip to content

Commit 6631235

Browse files
Core: Detect GOG installations using registry key
1 parent 7b57d87 commit 6631235

4 files changed

Lines changed: 67 additions & 9 deletions

File tree

src/7thHeaven.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ struct SeventhHeavenProvider: LauncherProductProviding {
1515
gameDisplayName: "Final Fantasy VII",
1616
steamGameDirectoryName: "FINAL FANTASY VII",
1717
steamGameIDs: ["39140", "3837340"],
18-
gogFallbackRelativePath: "drive_c/GOG Games/Final Fantasy VII",
18+
gogInstallRegistryKey: "HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\GOG.com\\Games\\1698970154",
1919
steamUserRelativePath: "Documents/Square Enix/FINAL FANTASY VII Steam/user_12345678",
2020
wineAppDefaultExeName: "7th Heaven.exe",
2121
wineDLLOverrides: "dinput=n,b",

src/JunctionVIII.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ struct JunctionVIIIProvider: LauncherProductProviding {
1515
gameDisplayName: "FINAL FANTASY VIII",
1616
steamGameDirectoryName: "FINAL FANTASY VIII",
1717
steamGameIDs: ["39150"],
18-
gogFallbackRelativePath: "drive_c/GOG Games/FINAL FANTASY VIII",
18+
gogInstallRegistryKey: "",
1919
steamUserRelativePath: "Documents/Square Enix/FINAL FANTASY VIII Steam/user_12345678",
2020
wineAppDefaultExeName: "Junction VIII.exe",
2121
wineDLLOverrides: "dinput=n,b",

src/Memoria.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ struct MemoriaProvider: LauncherProductProviding {
1515
gameDisplayName: "FINAL FANTASY IX",
1616
steamGameDirectoryName: "FINAL FANTASY IX",
1717
steamGameIDs: ["377840"],
18-
gogFallbackRelativePath: "drive_c/GOG Games/FINAL FANTASY IX",
18+
gogInstallRegistryKey: "HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432NODE\\GOG.com\\Games\\1375008492",
1919
steamUserRelativePath: "drive_c/Users/\(NSUserName())/AppData/LocalLow/SquareEnix/FINAL FANTASY IX/Steam/EncryptedSavedData",
2020
wineAppDefaultExeName: "FF9_Launcher.exe",
2121
wineDLLOverrides: "xaudio2_9=n,b",

src/main.swift

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ struct LauncherProduct {
3434
let gameDisplayName: String
3535
let steamGameDirectoryName: String
3636
let steamGameIDs: [String]
37-
let gogFallbackRelativePath: String
37+
let gogInstallRegistryKey: String
3838
let steamUserRelativePath: String
3939
let wineAppDefaultExeName: String
4040
let wineDLLOverrides: String
@@ -751,6 +751,52 @@ final class LauncherEngine {
751751
return nil
752752
}
753753

754+
private func readRegistryValue(keyPath: String, valueName: String) -> String? {
755+
let task = Process()
756+
task.executableURL = paths.wineBin
757+
task.arguments = ["reg", "query", keyPath, "/v", valueName]
758+
759+
let outputPipe = Pipe()
760+
task.standardOutput = outputPipe
761+
task.standardError = outputPipe
762+
763+
do {
764+
try task.run()
765+
task.waitUntilExit()
766+
} catch {
767+
log("Failed to query registry key \(keyPath): \(error.localizedDescription)")
768+
return nil
769+
}
770+
771+
guard task.terminationStatus == 0 else {
772+
log("Registry key not found or unreadable: \(keyPath) [value=\(valueName)]")
773+
return nil
774+
}
775+
776+
let outputData = outputPipe.fileHandleForReading.readDataToEndOfFile()
777+
guard let output = String(data: outputData, encoding: .utf8) else {
778+
log("Failed to decode registry output for key: \(keyPath)")
779+
return nil
780+
}
781+
782+
let escapedValueName = NSRegularExpression.escapedPattern(for: valueName)
783+
let pattern = "^\\s*\(escapedValueName)\\s+REG_\\w+\\s+(.+?)\\s*$"
784+
guard let regex = try? NSRegularExpression(pattern: pattern, options: [.anchorsMatchLines]) else {
785+
log("Failed to compile registry parsing regex for value: \(valueName)")
786+
return nil
787+
}
788+
789+
let range = NSRange(output.startIndex..., in: output)
790+
guard let match = regex.firstMatch(in: output, options: [], range: range),
791+
let valueRange = Range(match.range(at: 1), in: output) else {
792+
log("Registry value \(valueName) not found in key: \(keyPath)")
793+
return nil
794+
}
795+
796+
let value = String(output[valueRange]).trimmingCharacters(in: .whitespacesAndNewlines)
797+
return value.isEmpty ? nil : value
798+
}
799+
754800
private func findSteamGamePath() -> GameInstallLocation? {
755801
let steamConfig = FileManager.default.homeDirectoryForCurrentUser
756802
.appendingPathComponent("Library/Application Support/Steam/steamapps/libraryfolders.vdf")
@@ -854,18 +900,29 @@ final class LauncherEngine {
854900
}
855901

856902
private func findGOGGamePath() -> GameInstallLocation? {
857-
let gogPath = paths.winePrefix.appendingPathComponent(product.gogFallbackRelativePath).path
903+
let registryKey = product.gogInstallRegistryKey.trimmingCharacters(in: .whitespacesAndNewlines)
904+
guard !registryKey.isEmpty else {
905+
return nil
906+
}
907+
908+
guard let windowsPath = readRegistryValue(keyPath: registryKey, valueName: "path") else {
909+
return nil
910+
}
911+
912+
let gogURL = convertWindowsPathToPrefixPath(windowsPath)
913+
let gogPath = gogURL.path
858914

859915
if FileManager.default.fileExists(atPath: gogPath) {
860-
log("Found \(product.gameDisplayName) at GOG fallback: \(gogPath)")
916+
log("Found \(product.gameDisplayName) via GOG registry key: \(gogPath)")
861917
return GameInstallLocation(
862918
path: gogPath,
863-
installDir: URL(fileURLWithPath: gogPath).lastPathComponent,
919+
installDir: gogURL.lastPathComponent,
864920
gameID: "",
865921
libraryPath: ""
866922
)
867923
}
868924

925+
log("GOG registry path does not exist in prefix: \(gogPath)")
869926
return nil
870927
}
871928

@@ -1120,7 +1177,7 @@ final class LauncherEngine {
11201177
let presentAlert = {
11211178
let alert = NSAlert()
11221179
alert.messageText = "Path not found"
1123-
alert.informativeText = "Could not locate \(self.product.gameDisplayName) in Steam paths or GOG fallback path."
1180+
alert.informativeText = "Could not locate \(self.product.gameDisplayName) in Steam paths or GOG location."
11241181
alert.alertStyle = .warning
11251182
alert.addButton(withTitle: "OK")
11261183
NSApp.activate(ignoringOtherApps: true)
@@ -1201,11 +1258,12 @@ final class LauncherEngine {
12011258
showStatusMessage("Locating game path...", style: .informational)
12021259

12031260
if product.id == "memoria" {
1261+
let gogInPrefixPath = findGOGGamePath().map { URL(fileURLWithPath: $0.path) }
12041262
let winePrefixCandidates: [URL] = [
12051263
paths.gameDirectory,
12061264
paths.targetExe.deletingLastPathComponent(),
12071265
paths.winePrefix.appendingPathComponent("drive_c/Program Files (x86)/Steam/steamapps/common/\(product.steamGameDirectoryName)"),
1208-
paths.winePrefix.appendingPathComponent(product.gogFallbackRelativePath)
1266+
gogInPrefixPath
12091267
].compactMap { $0 }
12101268

12111269
guard let currentGamePath = winePrefixCandidates.first(where: {

0 commit comments

Comments
 (0)