Skip to content

Commit 1810e4b

Browse files
committed
Support Enable ARM translation layer
1 parent da10165 commit 1810e4b

File tree

4 files changed

+102
-42
lines changed

4 files changed

+102
-42
lines changed

HPEInstallation.cs

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@ class BackupFile(string installPath, string relativePath, string? name = null) :
1414
private readonly string Name = name ?? relativePath;
1515
public readonly string SourcePath = Path.Combine(installPath, relativePath);
1616
public readonly string BackupPath = Path.Combine(installPath, relativePath + ".bak");
17+
1718
public bool Exists()
1819
{
1920
return File.Exists(SourcePath);
2021
}
22+
2123
public bool BackupExists()
2224
{
2325
return File.Exists(BackupPath);
@@ -43,14 +45,13 @@ public void Backup()
4345
public void Restore()
4446
{
4547
Console.WriteLine($"\n\n############# Restore {Name}");
46-
if (BackupExists())
47-
{
48-
File.Copy(BackupPath, SourcePath, true);
49-
}
50-
else
48+
if (!BackupExists())
5149
{
5250
Console.WriteLine($"Warning: {Name} not found, skipped.");
51+
return;
5352
}
53+
54+
File.Copy(BackupPath, SourcePath, true);
5455
}
5556
}
5657

@@ -154,24 +155,21 @@ public void Unlock()
154155
Console.WriteLine("\n\n############# Patch bios.rom");
155156
UnlockCommand.PatchBios(bios.SourcePath);
156157

157-
serviceExe.Backup();
158+
serviceConfig.Backup();
158159
Console.WriteLine("\n\n############# Patch Service.exe.config");
159160
UnlockCommand.PatchKernelCmdline(serviceConfig.SourcePath);
160161

161-
serviceLib.Backup();
162-
163-
if (!Dev)
162+
if (serviceLib.Exists())
163+
{
164+
serviceLib.Backup();
165+
Console.WriteLine("\n\n############# Patch ServiceLib.dll");
166+
UnlockCommand.PatchServiceExe(serviceLib.BackupPath, serviceLib.SourcePath, Dev);
167+
}
168+
else
164169
{
165-
if (serviceLib.Exists())
166-
{
167-
Console.WriteLine("\n\n############# Patch ServiceLib.dll");
168-
UnlockCommand.PatchServiceExe(serviceLib.BackupPath, serviceLib.SourcePath);
169-
}
170-
else
171-
{
172-
Console.WriteLine("\n\n############# Patch Service.exe");
173-
UnlockCommand.PatchServiceExe(serviceExe.BackupPath, serviceExe.SourcePath);
174-
}
170+
serviceExe.Backup();
171+
Console.WriteLine("\n\n############# Patch Service.exe");
172+
UnlockCommand.PatchServiceExe(serviceExe.BackupPath, serviceExe.SourcePath, Dev);
175173
}
176174
}
177175

README.md

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,29 @@
1-
# Google Play Games Super Power
1+
# Magisk on Google Play Games Emulator
22

3-
Install Magisk on Google Play Games Emulator.
3+
## Features
44

5-
# Credits
5+
- Remove foreground app whitelist
6+
- Remove install apk restriction
7+
- Enable ARM translation layer (libhoudini)
68

7-
https://github.com/chsbuffer/hpesuperpower
8-
https://github.com/chsbuffer/superpower
9+
Note:
10+
11+
- The Developer Emulator has a Launcher and you can still play most of the games from Play Store.
12+
- To install apk on non-dev one, open Android Settings following the [guide](https://support.google.com/googleplaygamesonpc/answer/11507425?hl=en).
13+
14+
## Guide
15+
16+
1. Install Google Play Games Emulator Developer Emulator as I recommend it.
17+
2. Open the emulator once then close it.
18+
3. Get [this tool](https://github.com/chsbuffer/hpesuperpower/releases/latest) and [Magisk](https://github.com/topjohnwu/Magisk?tab=readme-ov-file#downloads)
19+
4. Run the command with Administrator Command Prompt
20+
```
21+
hpesuperpower.exe magisk Magisk.apk --dev
22+
```
23+
24+
## Credits
25+
26+
https://github.com/topjohnwu/Magisk
927
https://github.com/f1x3d/DiskPartitionInfo
1028
https://github.com/WearCode/magiskboot_build
1129
https://github.com/jbevain/cecil

UnlockCommand.cs

Lines changed: 61 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public static void PatchBios(string path)
2727
Console.WriteLine("hex not found, the bios might already been patched, nothing to do.");
2828
return;
2929
}
30+
3031
Console.WriteLine($"bios patched at {off:X8}");
3132
to.CopyTo(bios.AsSpan(off));
3233

@@ -40,50 +41,93 @@ public static void PatchKernelCmdline(string serviceConfigPath)
4041
const string to = "androidboot.verifiedbootstate=orange ";
4142
var xml = new XmlDocument();
4243
xml.Load(serviceConfigPath);
43-
var value = xml.SelectNodes("/configuration/applicationSettings/Google.Hpe.Service.Properties.EmulatorSettings/setting[@name='EmulatorGuestParameters']/value")!.Item(0)!;
44+
var value = xml.SelectNodes(
45+
"/configuration/applicationSettings/Google.Hpe.Service.Properties.EmulatorSettings/setting[@name='EmulatorGuestParameters']/value")
46+
!.Item(0)!;
4447

4548
var oldParam = value.InnerText;
4649
if (oldParam.Contains(to))
4750
{
4851
Console.WriteLine("Service.exe.config already modified, nothing to do.");
4952
return;
5053
}
54+
5155
value.InnerText = to + value.InnerText;
5256
xml.Save(serviceConfigPath);
5357
Console.WriteLine("Service.exe.config modified.");
5458
}
5559

56-
public static void PatchServiceExe(string exePath, string outPath)
60+
public static void PatchServiceExe(string exePath, string outPath, bool isDev)
5761
{
5862
// remove foreground white-list
5963

6064
using var popCwd = new Pushd(Path.GetDirectoryName(exePath)!);
6165

62-
var assembly = AssemblyDefinition.ReadAssembly(exePath, new ReaderParameters { AssemblyResolver = new DefaultAssemblyResolver() });
66+
var assembly = AssemblyDefinition.ReadAssembly(exePath);
6367
var module = assembly.MainModule;
6468

65-
// System.Void Google.Hpe.Service.AppSession.AppSessionScope::HandleEmulatorSurfaceStateUpdate(Google.Hpe.Service.Emulator.Surface.EmulatorSurfaceState,Google.Hpe.Service.Emulator.Surface.EmulatorSurfaceState)
66-
var AppSessionScope = module.GetType("Google.Hpe.Service.AppSession.AppSessionScope");
67-
var method = AppSessionScope.Methods.Single(x => x.Name == "HandleEmulatorSurfaceStateUpdate");
68-
var instructions = method.Body.Instructions;
69+
Console.WriteLine($"Version: {assembly.Name.FullName}");
6970

70-
var begin = instructions.FirstOrDefault(p => p.Operand is FieldDefinition f && f.Name == "_transientForegroundPackages");
71+
#region Foreground app limit
7172

72-
if (begin == null)
73+
if (!isDev)
7374
{
74-
Console.WriteLine("nothing to patch.");
75-
return;
75+
Console.WriteLine("* Remove Foreground app limit. *");
76+
RemoveForegroundLimit();
7677
}
77-
Console.WriteLine($"Version: {assembly.Name.FullName}");
7878

79-
var idx = instructions.IndexOf(begin);
80-
Console.WriteLine($"Patch Instruction at idx {idx}, offset IL_{begin.Offset:X4}");
79+
void RemoveForegroundLimit()
80+
{
81+
// System.Void Google.Hpe.Service.AppSession.AppSessionScope::HandleEmulatorSurfaceStateUpdate(Google.Hpe.Service.Emulator.Surface.EmulatorSurfaceState,Google.Hpe.Service.Emulator.Surface.EmulatorSurfaceState)
82+
var AppSessionScope = module.GetType("Google.Hpe.Service.AppSession.AppSessionScope");
83+
var method = AppSessionScope.Methods.Single(x => x.Name == "HandleEmulatorSurfaceStateUpdate");
84+
var instructions = method.Body.Instructions;
85+
var begin = instructions.FirstOrDefault(p =>
86+
p.Operand is FieldDefinition { Name: "_transientForegroundPackages" });
87+
88+
if (begin == null)
89+
{
90+
Console.WriteLine("nothing to patch.");
91+
return;
92+
}
93+
94+
var idx = instructions.IndexOf(begin);
95+
Console.WriteLine($"Patch Instruction at idx {idx}, offset IL_{begin.Offset:X4}");
96+
97+
while (instructions[idx].OpCode != OpCodes.Leave_S)
98+
{
99+
instructions.RemoveAt(idx);
100+
}
101+
}
102+
103+
#endregion Foreground app limit
104+
105+
#region Houdini
81106

82-
while (instructions[idx].OpCode != OpCodes.Leave_S)
107+
Console.WriteLine("* Enable ARM translation layer (libhoudini). *");
108+
EnableHoudini(isDev);
109+
110+
void EnableHoudini(bool dev)
83111
{
84-
instructions.RemoveAt(idx);
112+
string className = dev
113+
? "Google.Hpe.Service.KiwiEmulator.EmulatorFeaturePolicyDev"
114+
: "Google.Hpe.Service.KiwiEmulator.EmulatorFeaturePolicyProd";
115+
116+
var clazz = module.GetType(className);
117+
var field = clazz.Fields.Single(it => it.Name.Contains("IsHoudiniEnabled"));
118+
foreach (var ctor in clazz.Methods.Where(it => it.IsConstructor && !it.IsStatic))
119+
{
120+
var proc = ctor.Body.GetILProcessor();
121+
var ret = ctor.Body.Instructions.Last();
122+
proc.InsertBefore(ret, proc.Create(OpCodes.Ldarg_0));
123+
proc.InsertBefore(ret, proc.Create(OpCodes.Ldc_I4_1));
124+
proc.InsertBefore(ret, proc.Create(OpCodes.Stfld, field));
125+
}
85126
}
86127

128+
129+
#endregion Houdini
130+
87131
assembly.Write(outPath);
88132
}
89-
}
133+
}

hpesuperpower.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<Nullable>enable</Nullable>
88
<AnalysisLevel>latest-recommended</AnalysisLevel>
99
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
10-
<Version>1.1.1</Version>
10+
<Version>1.2.0</Version>
1111
</PropertyGroup>
1212

1313
<ItemGroup>

0 commit comments

Comments
 (0)