Skip to content

Commit 2156f8e

Browse files
committed
update
1 parent a815183 commit 2156f8e

7 files changed

Lines changed: 118 additions & 2 deletions

File tree

HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import org.jackhuang.hmcl.util.io.FileUtils;
4848
import org.jackhuang.hmcl.util.io.ResponseCodeException;
4949
import org.jackhuang.hmcl.util.platform.*;
50+
import org.jackhuang.hmcl.util.platform.windows.WinReg;
5051
import org.jackhuang.hmcl.util.versioning.GameVersionNumber;
5152
import org.jackhuang.hmcl.util.versioning.VersionNumber;
5253

@@ -65,6 +66,7 @@
6566

6667
import static javafx.application.Platform.runLater;
6768
import static javafx.application.Platform.setImplicitExit;
69+
import static org.jackhuang.hmcl.setting.ConfigHolder.config;
6870
import static org.jackhuang.hmcl.ui.FXUtils.runInFX;
6971
import static org.jackhuang.hmcl.util.DataSizeUnit.MEGABYTES;
7072
import static org.jackhuang.hmcl.util.Lang.resolveException;
@@ -84,6 +86,7 @@ public final class LauncherHelper {
8486
private boolean showLogs;
8587
private QuickPlayOption quickPlayOption;
8688
private boolean disableOfflineSkin = false;
89+
private boolean gpuRegAlreadyExistsed = false;
8790

8891
public LauncherHelper(Profile profile, Account account, String selectedVersion) {
8992
this.profile = Objects.requireNonNull(profile);
@@ -207,6 +210,24 @@ private void launch0() {
207210
if (quickPlayOption != null) {
208211
launchOptionsBuilder.setQuickPlayOption(quickPlayOption);
209212
}
213+
if (config().isWindowsHighPerformance()) {
214+
Object current = WinReg.INSTANCE.queryValue(
215+
WinReg.HKEY.HKEY_CURRENT_USER,
216+
"Software\\Microsoft\\DirectX\\UserGpuPreferences",
217+
FileUtils.getAbsolutePath(javaVersionRef.get().getBinary())
218+
);
219+
if (current instanceof String) {
220+
gpuRegAlreadyExistsed = true;
221+
} else {
222+
WinReg.INSTANCE.setValue(
223+
WinReg.HKEY.HKEY_CURRENT_USER,
224+
"Software\\Microsoft\\DirectX\\UserGpuPreferences",
225+
FileUtils.getAbsolutePath(javaVersionRef.get().getBinary()),
226+
"GpuPreference=2;"
227+
);
228+
}
229+
}
230+
210231
LaunchOptions launchOptions = launchOptionsBuilder.create();
211232

212233
LOG.info("Here's the structure of game mod directory:\n" + FileUtils.printFileStructure(repository.getModsDirectory(selectedVersion), 10));
@@ -822,6 +843,16 @@ public void run() {
822843
}
823844

824845
private void finishLaunch() {
846+
if (!gpuRegAlreadyExistsed && config().isWindowsHighPerformance()) {
847+
try {
848+
Thread.sleep(5000L);
849+
} catch (InterruptedException ignored) {}
850+
WinReg.INSTANCE.deleteValue(
851+
WinReg.HKEY.HKEY_CURRENT_USER,
852+
"Software\\Microsoft\\DirectX\\UserGpuPreferences",
853+
process.getProcess().info().command().orElseThrow()
854+
);
855+
}
825856
switch (launcherVisibility) {
826857
case HIDE_AND_REOPEN:
827858
runLater(() -> {

HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -666,11 +666,11 @@ public BooleanProperty windowsHighPerformanceProperty() {
666666
return windowsHighPerformance;
667667
}
668668

669-
public boolean iswindowsHighPerformance() {
669+
public boolean isWindowsHighPerformance() {
670670
return windowsHighPerformance.get();
671671
}
672672

673-
public void setwindowsHighPerformance(boolean windowsHighPerformance) {
673+
public void setWindowsHighPerformance(boolean windowsHighPerformance) {
674674
this.windowsHighPerformance.set(windowsHighPerformance);
675675
}
676676

HMCL/src/main/resources/assets/lang/I18N.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,6 +1413,7 @@ settings.launcher.brightness.light=Light Mode
14131413
settings.launcher.common_path.tooltip=HMCL will put all game assets and dependencies here. If there are existing libraries in the game directory, then HMCL will prefer to use them first.
14141414
settings.launcher.debug=Debug
14151415
settings.launcher.disable_auto_game_options=Do not switch game language
1416+
settings.launcher.windows_gpu_preferences=[Windows] Automatically launch games using the high-performance GPU
14161417
settings.launcher.download=Download
14171418
settings.launcher.download.threads=Threads
14181419
settings.launcher.download.threads.auto=Automatically Determine

HMCL/src/main/resources/assets/lang/I18N_zh.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,6 +1193,7 @@ settings.launcher.brightness.light=淺色模式
11931193
settings.launcher.common_path.tooltip=啟動器將所有遊戲資源及相依元件庫檔案放於此集中管理。如果遊戲目錄內有現成的將不會使用公共庫檔案。
11941194
settings.launcher.debug=除錯
11951195
settings.launcher.disable_auto_game_options=不自動切換遊戲語言
1196+
settings.launcher.windows_gpu_preferences=[Windows] 自動使用高效能 GPU 啟動遊戲
11961197
settings.launcher.download=下載
11971198
settings.launcher.download.threads=執行緒數
11981199
settings.launcher.download.threads.auto=自動選取執行緒數

HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/windows/Advapi32.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,22 @@ int RegEnumKeyExW(Pointer hKey, int dwIndex,
5656
IntByReference lpReserved,
5757
Pointer lpClass, IntByReference lpcchClass,
5858
Pointer lpftLastWriteTime);
59+
60+
/**
61+
* @see <a href="https://learn.microsoft.com/windows/win32/api/winreg/nf-winreg-regcreatekeyexw">RegCreateKeyExW function</a>
62+
*/
63+
int RegCreateKeyExW(Pointer hKey, WString lpSubKey, int Reserved, WString lpClass,
64+
int dwOptions, int samDesired, Pointer lpSecurityAttributes,
65+
PointerByReference phkResult, IntByReference lpdwDisposition);
66+
67+
/**
68+
* @see <a href="https://learn.microsoft.com/windows/win32/api/winreg/nf-winreg-regsetvalueexw">RegSetValueExW function</a>
69+
*/
70+
int RegSetValueExW(Pointer hKey, WString lpValueName, int Reserved, int dwType,
71+
Pointer lpData, int cbData);
72+
73+
/**
74+
* @see <a href="https://learn.microsoft.com/windows/win32/api/winreg/nf-winreg-regdeletevaluew">RegDeleteValueW function</a>
75+
*/
76+
int RegDeleteValueW(Pointer hKey, WString lpValueName);
5977
}

HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/windows/WinConstants.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ public interface WinConstants {
5353
// https://learn.microsoft.com/windows/win32/sysinfo/registry-key-security-and-access-rights
5454
int KEY_QUERY_VALUE = 0x0001;
5555
int KEY_ENUMERATE_SUB_KEYS = 0x0008;
56+
int KEY_WRITE = 0x20006;
57+
int KEY_SET_VALUE = 0x0002;
5658
int KEY_READ = 0x20019;
5759

5860
// https://learn.microsoft.com/windows/win32/sysinfo/registry-value-types
@@ -100,4 +102,6 @@ public interface WinConstants {
100102
// https://learn.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute
101103
int DWMWA_USE_IMMERSIVE_DARK_MODE = 20;
102104

105+
// https://learn.microsoft.com/windows/win32/api/winreg/nf-winreg-regcreatekeyexw
106+
int REG_OPTION_NON_VOLATILE = 0x0000;
103107
}

HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/windows/WinReg.java

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ public List<String> querySubKeys(HKEY root, String key) {
8888
return list;
8989
}
9090

91+
public abstract boolean setValue(HKEY root, String key, String valueName, String value);
92+
93+
public abstract boolean deleteValue(HKEY root, String key, String valueName);
94+
9195
private static final class JNAWinReg extends WinReg {
9296

9397
private final Advapi32 advapi32;
@@ -245,6 +249,63 @@ public List<String> querySubKeyNames(HKEY root, String key) {
245249

246250
return Collections.emptyList();
247251
}
252+
253+
@Override
254+
public boolean setValue(HKEY root, String key, String valueName, String value) {
255+
PointerByReference phkKey = new PointerByReference();
256+
int status = advapi32.RegCreateKeyExW(
257+
root.toPointer(),
258+
new WString(key),
259+
0,
260+
null,
261+
WinConstants.REG_OPTION_NON_VOLATILE,
262+
WinConstants.KEY_WRITE,
263+
null,
264+
phkKey,
265+
null
266+
);
267+
268+
if (status != WinConstants.ERROR_SUCCESS) {
269+
return false;
270+
}
271+
272+
Pointer hkey = phkKey.getValue();
273+
try {
274+
byte[] data = (value + "\0").getBytes(StandardCharsets.UTF_16LE);
275+
try (Memory mem = new Memory(data.length)) {
276+
mem.write(0, data, 0, data.length);
277+
status = advapi32.RegSetValueExW(
278+
hkey,
279+
new WString(valueName),
280+
0,
281+
WinConstants.REG_SZ,
282+
mem,
283+
data.length
284+
);
285+
}
286+
return status == WinConstants.ERROR_SUCCESS;
287+
} finally {
288+
advapi32.RegCloseKey(hkey);
289+
}
290+
}
291+
292+
@Override
293+
public boolean deleteValue(HKEY root, String key, String valueName) {
294+
PointerByReference phkKey = new PointerByReference();
295+
int status = advapi32.RegOpenKeyExW(root.toPointer(), new WString(key), 0, WinConstants.KEY_SET_VALUE, phkKey);
296+
297+
if (status != WinConstants.ERROR_SUCCESS) {
298+
return false;
299+
}
300+
301+
Pointer hkey = phkKey.getValue();
302+
try {
303+
status = advapi32.RegDeleteValueW(hkey, new WString(valueName));
304+
return status == WinConstants.ERROR_SUCCESS;
305+
} finally {
306+
advapi32.RegCloseKey(hkey);
307+
}
308+
}
248309
}
249310

250311
}

0 commit comments

Comments
 (0)