Skip to content

Commit 0d58048

Browse files
authored
Merge pull request #6 from 2228293026/main
docs(readme): 补充构建前置条件与 cimgui 符号链接说明,新增中文版 README
2 parents f1c88ee + 891dc6b commit 0d58048

3 files changed

Lines changed: 264 additions & 8 deletions

File tree

‎GET_STARTED.md‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,22 @@
66

77
### 构建
88

9+
前置条件:
10+
11+
- .NET 10 SDK
12+
- Visual Studio:**使用 C++ 的桌面开发** 工作负载(MSVC + Windows SDK)
13+
- **适用于 Windows 的 C++ CMake 工具**(CMake + Ninja,需在 PATH)
14+
- 开启 Windows **开发者模式**,克隆后还原 cimgui 符号链接(详见
15+
[README · Build](README.md#build)),否则 CMake 找不到 cimgui 源码:
16+
17+
```bash
18+
git config core.symlinks true
19+
rm StArray.ModManager.Windows/Native/cimgui Android/library/src/main/cpp/libs/cimgui
20+
git checkout -- StArray.ModManager.Windows/Native/cimgui Android/library/src/main/cpp/libs/cimgui
21+
```
22+
23+
然后:
24+
925
```bash
1026
git clone --recurse-submodules https://github.com/StArraySharp/StArray.ModManager.git
1127
dotnet build StArray.ModManager.Windows -c Release

‎README.md‎

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# StArray.ModManager
22

3+
English | [简体中文](README.zh-CN.md)
4+
35
Android IL2CPP Unity mod manager with CoreCLR runtime embedding and ImGui overlay UI.
46

57
## How It Works
@@ -123,7 +125,10 @@ Generated partial class provides `InstallHooks()` / `UninstallHooks()` with `*Or
123125

124126
## Build
125127

126-
Requires .NET 10 SDK + Android NDK (cmake on PATH).
128+
| Platform | Requirements |
129+
|----------|--------------|
130+
| Windows | .NET 10 SDK; Visual Studio with **Desktop development with C++** (MSVC + Windows SDK) and **C++ CMake tools for Windows** (CMake + Ninja on PATH) |
131+
| Android | Android NDK (cmake on PATH) |
127132

128133
```bash
129134
# Windows (native + C#, one command)
@@ -133,6 +138,23 @@ dotnet build StArray.ModManager.Windows -c Release
133138
cd Android && ./gradlew :library:assembleRelease
134139
```
135140

141+
### Windows: restore the cimgui symlinks after cloning
142+
143+
`StArray.ModManager.CImGui/` is the shared cimgui source used by both
144+
platforms. The Windows and Android native builds reach it through two git
145+
symlinks (`StArray.ModManager.Windows/Native/cimgui`,
146+
`Android/library/src/main/cpp/libs/cimgui`), which on Windows only materialize
147+
as real links with **Developer Mode** enabled (or an elevated shell) —
148+
otherwise they are checked out as plain text files and the CMake build fails
149+
with missing `cimgui` references. One-time fix after cloning:
150+
151+
```bash
152+
# 1. Enable Windows Developer Mode first, then:
153+
git config core.symlinks true
154+
rm StArray.ModManager.Windows/Native/cimgui Android/library/src/main/cpp/libs/cimgui
155+
git checkout -- StArray.ModManager.Windows/Native/cimgui Android/library/src/main/cpp/libs/cimgui
156+
```
157+
136158
## Windows Architecture
137159

138160
The native DLL (`StArray.ModManager.Windows.Native.dll`) uses
@@ -143,10 +165,10 @@ The native DLL (`StArray.ModManager.Windows.Native.dll`) uses
143165

144166
| File | Backend | Init | Render |
145167
|------|---------|------|--------|
146-
| `hook_d3d12.cpp` | D3D12 | Descriptor heaps, command list, RTV per-frame contexts | Resource barriers + OMSetRenderTargets |
147-
| `hook_d3d11.cpp` | D3D11 | Device + Context + persistent backbuffer RTV | OMSetRenderTargets + RenderDrawData |
148-
| `hook_d3d9.cpp` | D3D9 | SwapChain QI → Device | Viewport/scissor save-restore |
149-
| `main.cpp` | GL/VK | Win32 init only (C# handles backend) | C# render callback only |
168+
| `dx12hook.cpp` | D3D12 | Descriptor heaps, command list, RTV per-frame contexts | Resource barriers + OMSetRenderTargets |
169+
| `dx11hook.cpp` | D3D11 | Device + Context + persistent backbuffer RTV | OMSetRenderTargets + RenderDrawData |
170+
| `dx9hook.cpp` | D3D9 | SwapChain QI → Device | Viewport/scissor save-restore |
171+
| `main.cpp` | GL/VK | Win32 init only (C# handles backend) | C# render callback only |
150172

151173
**Unified dispatch** (`main.cpp` `hkPresent`):
152174
- All backends share `DisplaySize`, `ImGui_ImplWin32_NewFrame`, WndProc hook
@@ -158,9 +180,9 @@ flowchart LR
158180
CSharp[C# ImGuiRenderer] -->|P/Invoke Init| Native[Native DLL]
159181
Native -->|kiero2 detect| API[D3D9/11/12/GL/VK]
160182
API -->|MinHook| Present[hkPresent]
161-
Present -->|dispatch| D3D11[hook_d3d11]
162-
Present -->|dispatch| D3D12[hook_d3d12]
163-
Present -->|dispatch| D3D9[hook_d3d9]
183+
Present -->|dispatch| D3D11[dx11hook]
184+
Present -->|dispatch| D3D12[dx12hook]
185+
Present -->|dispatch| D3D9[dx9hook]
164186
D3D11 & D3D12 & D3D9 -->|callback| CSharp
165187
CSharp -->|ImGui.NET| cimgui[cimgui.dll]
166188
```
@@ -175,6 +197,12 @@ flowchart LR
175197

176198
```bash
177199
git clone --recurse-submodules https://github.com/StArraySharp/StArray.ModManager.git
200+
```
201+
202+
On Windows, complete the one-time cimgui symlink setup in
203+
[Build](#build) before running `dotnet build`, then:
204+
205+
```bash
178206
dotnet build StArray.ModManager.Windows -c Release
179207
```
180208

‎README.zh-CN.md‎

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
# StArray.ModManager
2+
3+
[English](README.md) | 简体中文
4+
5+
Android IL2CPP Unity Mod 管理器,内嵌 CoreCLR 运行时并使用 ImGui 覆盖层 UI。
6+
7+
## 工作原理
8+
9+
1. **原生注入** — `libmodmanager.so` 加载进 Unity 进程
10+
2. **Dobby hook** — 钩住 `eglSwapBuffers` 与 Android 输入事件
11+
3. **运行时内嵌 CoreCLR** — 从 JNI 启动 .NET 托管代码
12+
4. **UnityResolve** 反射引擎遍历 IL2CPP/Mono 托管类型
13+
5. **ImGui 覆盖层** — 通过 EGL + OpenGL ES 渲染,支持触摸与键盘 IME
14+
15+
## 功能特性
16+
17+
- 基于 Dobby 的 **eglSwapBuffers hook** — 每帧渲染 ImGui 覆盖层
18+
- **触摸与按键输入** — InputConsumer hook + cimgui Android 后端
19+
- **IME 输入法支持**(中文/日文)— 自定义 KeyboardView + InputConnection 桥接
20+
- **Mod 系统** — 扫描/加载/卸载 + 依赖解析 + 重启自动启用
21+
- **Mod 覆盖层 API** — `OnBackgroundGUI` / `OnForegroundGUI` 直接绘制到游戏画面
22+
- **自动更新** — OTA 版本检查 + 下载 + SHA-256 校验 + 重启
23+
- **配置持久化** — STJ source-gen JSON,AOT 兼容
24+
- **文件日志** — 双写 logcat + `manager.log`
25+
- **GL 调试面板** — caps 开关、混合/深度函数选择器、GL 状态查询
26+
- **FontAwesome 7** 图标 — 内嵌资源
27+
- **IImGuiRenderer** 接口 — 可在 EGL、Vulkan 后端间切换
28+
- **CoreCLR 参数** — 从 Java 传 `string[]` 给托管 `Entry(int, IntPtr)`
29+
- **CoreCLR 打包进 AAR** — `copyCoreClrToJniLibs` 把运行时 .so 拷入 jniLibs
30+
31+
## API 参考
32+
33+
### Mod 入口
34+
35+
| 接口 | 方法 | 说明 |
36+
|------|------|------|
37+
| `IModPlugin` | `OnLoad()` | Mod 加载时调用 |
38+
| | `OnUnload()` | Mod 卸载时调用 |
39+
| | `OnBackgroundGUI(ImDrawListPtr)` | 在 ImGui 窗口后方绘制 |
40+
| | `OnForegroundGUI(ImDrawListPtr)` | 在 ImGui 窗口上方绘制 |
41+
| `IModSettings` | `OnGui()` | 在 ModManager 中绘制自定义设置页 |
42+
43+
### Hook
44+
45+
`[NativeHook]` 支持三种模式:
46+
47+
| 特性 | 说明 |
48+
|------|------|
49+
| `[NativeHook("lib.so", "symbolName")]` | 符号导出 hook — 用 `dlsym` 解析 |
50+
| `[NativeHook("lib.so", 0x1234)]` | RVA hook — 用 `GetFuncPtr(base + 0x1234)` |
51+
| `[NativeHook(nameof(ResolverMethod))]` | 解析器模式 — 引用同类中的 `static nint ResolverMethod()`;支持 `"Namespace.Type.Method"` 跨类引用 |
52+
53+
生成的 partial class 提供 `InstallHooks()` / `UninstallHooks()`,以及用于调用原函数的 `*Original` 委托。
54+
55+
### Stub(类型化游戏对象包装)
56+
57+
| 基类 | 说明 |
58+
|------|------|
59+
| `UnmanagedObject` | 包装 `nint` 指针,提供 `Obj` 字段用于运行时访问 |
60+
| `Wrap<T>(nint ptr)` | 返回包装指定指针的类型化 stub |
61+
62+
### 运行时反射
63+
64+
| 类 | 关键方法 | 说明 |
65+
|----|---------|------|
66+
| `RuntimeObject` | `GetField<T>(string)` / `SetField(string, T)` | 读/写实例字段 |
67+
| | `Invoke<T>(string, params object[])` | 调用实例方法 |
68+
| | `GetProperty<T>(string)` / `SetProperty(string, T)` | 读/写属性 |
69+
| `RuntimeArray<T>` | `new RuntimeArray<T>(nint ptr)` | 强类型数组包装 |
70+
| | `.Length` / `[index]` | 数组长度与元素访问 |
71+
| `RuntimeManager` | `GetDomain()` / `IsIl2Cpp` | 检测当前运行时并获取 domain |
72+
| `IAppDomain` | `OpenAssembly(string)` | 打开已加载的程序集 |
73+
| `IRuntimeAssembly` | `GetClass(string ns, string name)` | 按命名空间 + 类名获取类 |
74+
| `IRuntimeClass` | `GetMethod(string, int)` / `GetField(string)` | 获取可调用的方法/字段 |
75+
| `IRuntimeMethod` | `Invoke(nint thisPtr, params object[])` / `InvokeStatic()` | 调用方法 |
76+
| `IRuntimeField` | `GetValue<T>(nint)` / `SetValue(nint, T)` | 读/写字段 |
77+
78+
### NativeFuncResolver
79+
80+
| 方法 | 说明 |
81+
|------|------|
82+
| `FindRva(string symbol, byte?[]? pattern)` | 符号 → RVA,失败回退特征码扫描 |
83+
| `FindSymbolRva(string)` | 在 `.dynsym` + `.dynstr` 中精确匹配符号名 |
84+
| `FindRva(byte?[] pattern)` | 对 `.text` 段做特征码扫描 |
85+
| `ParseHexPattern(string)` | 把 `"48 89 ?? ?? ?? ?? ?? ff"` 转成匹配模式 |
86+
| `Resolve(string, byte?[]?)` | 加载库 + 查找 + 返回函数指针 |
87+
88+
### 设置特性
89+
90+
| 特性 | 参数 | 说明 |
91+
|------|------|------|
92+
| `[ModSettingLabel("text")]` | `string` | 设置字段的显示标签 |
93+
| `[ModSettingLabelSide(ModInspector.LabelSide)]` | `Left` / `Right` | 标签位置 |
94+
| `[ModSettingRange(min, max)]` | `float, float` | 数值夹取范围 |
95+
| `[ModSettingJson(Lines = N)]` | `int` | 多行 JSON 编辑器 |
96+
97+
### Inspector
98+
99+
| 方法 | 说明 |
100+
|--------|------|
101+
| `ModInspector.Draw(object)` | 为所有带 `[ModSettingLabel]` 的字段自动生成 UI |
102+
103+
### 工具类
104+
105+
| 类 | 说明 |
106+
|----|------|
107+
| `Logger` | `Info(string)`、`Warn(string)`、`Error(string)` — 统一日志 |
108+
| `HookHelper` | `Instance` — 设为你的 hook 实现;`GetFunctionRVA` / `GetFunctionRVAFallback` |
109+
| `BehaviourManager` | 在 Unity 生命周期事件上调度操作 |
110+
| `DL` | 跨平台 `Open` / `Symbol` / `Close` / `Error` / `Addr` / `GetBaseAddress` |
111+
112+
## 第三方库
113+
114+
| 库 | 许可证 | 用于 |
115+
|----|--------|------|
116+
| [Dear ImGui](https://github.com/ocornut/imgui) | MIT | UI 渲染 |
117+
| [cimgui](https://github.com/cimgui/cimgui) | MIT | ImGui C API 绑定 |
118+
| [ImGui.NET](https://github.com/ImGuiNET/ImGui.NET) | MIT | C# ImGui 绑定 |
119+
| [kiero2](https://github.com/kirchesz/kiero2) | MIT | 图形 API 检测 (D3D9/11/12/GL/VK) |
120+
| [MinHook](https://github.com/TsudaKageyu/minhook) | BSD-2 | API hook |
121+
| [Corehold](https://github.com/StArraySharp/Corehold) | MIT | winmm 代理 DLL + CoreCLR 宿主 |
122+
| [Dobby](https://github.com/jmpews/Dobby) | Apache-2.0 | Android inline hook |
123+
| [CoreCLR](https://github.com/dotnet/runtime) | MIT | .NET 运行时 |
124+
| [FontAwesome 7](https://fontawesome.com) | OFL/SIL | 图标字体 |
125+
126+
## 构建
127+
128+
| 平台 | 前置条件 |
129+
|------|----------|
130+
| Windows | .NET 10 SDK;Visual Studio 并安装 **使用 C++ 的桌面开发**(MSVC + Windows SDK)与 **适用于 Windows 的 C++ CMake 工具**(CMake + Ninja 需在 PATH) |
131+
| Android | Android NDK(cmake 需在 PATH) |
132+
133+
```bash
134+
# Windows(原生 + C#,一条命令)
135+
dotnet build StArray.ModManager.Windows -c Release
136+
137+
# Android
138+
cd Android && ./gradlew :library:assembleRelease
139+
```
140+
141+
### Windows:克隆后还原 cimgui 符号链接
142+
143+
`StArray.ModManager.CImGui/` 是两个平台共享的 cimgui 源码。Windows 与 Android
144+
原生构建通过两个 git 符号链接(`StArray.ModManager.Windows/Native/cimgui`、
145+
`Android/library/src/main/cpp/libs/cimgui`)接入;在 Windows 上只有开启
146+
**开发者模式**(或使用管理员 shell)时它们才会被还原成真正的链接——否则会被检出为
147+
纯文本文件,CMake 构建因缺少 `cimgui` 引用而失败。克隆后一次性修复:
148+
149+
```bash
150+
# 1. 先开启 Windows 开发者模式,然后:
151+
git config core.symlinks true
152+
rm StArray.ModManager.Windows/Native/cimgui Android/library/src/main/cpp/libs/cimgui
153+
git checkout -- StArray.ModManager.Windows/Native/cimgui Android/library/src/main/cpp/libs/cimgui
154+
```
155+
156+
## Windows 架构
157+
158+
原生 DLL(`StArray.ModManager.Windows.Native.dll`)使用
159+
[kiero2](https://github.com/kirchesz/kiero2) 检测图形 API,用
160+
[MinHook](https://github.com/TsudaKageyu/minhook) 钩住 `Present`。
161+
162+
**按后端拆分的 hook 文件**(`Native/`):
163+
164+
| 文件 | 后端 | 初始化 | 渲染 |
165+
|------|------|--------|------|
166+
| `dx12hook.cpp` | D3D12 | 描述符堆、命令列表、逐帧 RTV 上下文 | 资源屏障 + OMSetRenderTargets |
167+
| `dx11hook.cpp` | D3D11 | Device + Context + 持久化后台缓冲 RTV | OMSetRenderTargets + RenderDrawData |
168+
| `dx9hook.cpp` | D3D9 | SwapChain QI → Device | 视口/裁剪矩形保存-恢复 |
169+
| `main.cpp` | GL/VK | 仅 Win32 初始化(C# 处理后端) | 仅 C# 渲染回调 |
170+
171+
**统一分发**(`main.cpp` 的 `hkPresent`):
172+
- 所有后端共享 `DisplaySize`、`ImGui_ImplWin32_NewFrame`、WndProc hook
173+
- `DEBUG_LOG` 条件编译(`NDEBUG` → Release 下编译剔除)
174+
- 窗口句柄取自 `SwapChain::GetDesc().OutputWindow`
175+
176+
```mermaid
177+
flowchart LR
178+
CSharp[C# ImGuiRenderer] -->|P/Invoke Init| Native[Native DLL]
179+
Native -->|kiero2 detect| API[D3D9/11/12/GL/VK]
180+
API -->|MinHook| Present[hkPresent]
181+
Present -->|dispatch| D3D11[dx11hook]
182+
Present -->|dispatch| D3D12[dx12hook]
183+
Present -->|dispatch| D3D9[dx9hook]
184+
D3D11 & D3D12 & D3D9 -->|callback| CSharp
185+
CSharp -->|ImGui.NET| cimgui[cimgui.dll]
186+
```
187+
188+
## 目标平台
189+
190+
- Windows x64(D3D9/11/12)— DLL 注入或 CoreCLR 宿主
191+
- Android arm64-v8a(OpenGL ES)— IL2CPP Unity 游戏(API 26+)
192+
- CoreCLR .NET 10 运行时
193+
194+
## 快速开始
195+
196+
```bash
197+
git clone --recurse-submodules https://github.com/StArraySharp/StArray.ModManager.git
198+
```
199+
200+
Windows 上请先完成 [构建](#构建) 章节中的一次性 cimgui 符号链接设置,再运行:
201+
202+
```bash
203+
dotnet build StArray.ModManager.Windows -c Release
204+
```
205+
206+
注入与构建说明见 [GET_STARTED.md](GET_STARTED.md)。
207+
208+
运行时程序集可从 [runtime-references release](https://github.com/StArraySharp/StArray.ModManager/releases/tag/0) 下载。
209+
210+
---
211+
212+
大部分代码由 AI 生成。

0 commit comments

Comments
 (0)