diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml
index df9d134..755ebc2 100644
--- a/.github/workflows/check.yml
+++ b/.github/workflows/check.yml
@@ -16,6 +16,7 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
+ fetch-depth: 0
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: 24
@@ -23,5 +24,12 @@ jobs:
run: npm ci --ignore-scripts
- name: Build the site (fails on dead links)
run: npm run build
+ - name: Check that Chinese and English pages match
+ run: python3 scripts/i18n.py
+ - name: Warn when a page changed in one language only
+ if: github.event_name == 'pull_request'
+ env:
+ BASE_REF: ${{ github.base_ref }}
+ run: python3 scripts/i18n.py --base "origin/$BASE_REF"
- name: Scan tracked files for private identity and paths
run: python3 scripts/privacy.py .
diff --git a/README.en.md b/README.en.md
new file mode 100644
index 0000000..55fcf34
--- /dev/null
+++ b/README.en.md
@@ -0,0 +1,33 @@
+# ModAVD documentation site
+
+[简体中文](README.md) | **English**
+
+
+
+The source of the documentation site for [ModAVD](https://github.com/ModAVD/ModAVD), published at (English version: ). It is built with [VitePress](https://vitepress.dev/).
+
+- Pages are Markdown files under `docs/`, and Chinese is the primary language. English pages are under `docs/en/`, at the same paths as the Chinese pages. The navigation and sidebar are in `docs/.vitepress/config.mts`, and both languages use one table of pages.
+- Every page has an "Edit this page on GitHub" link at the bottom; make your change and open a PR. How to write pages is described on the site under "Contributing → Documentation and this site".
+- If you change a page in one language, change the other language in the same PR. If you only write one of the two, say so in the PR and the maintainer will add the other.
+
+## Preview locally
+
+You need Node.js 24.
+
+```powershell
+npm ci --ignore-scripts
+npm run dev # local preview
+npm run build # builds docs/.vitepress/dist; dead links fail the build
+python scripts/i18n.py # checks the Chinese and English pages and headings, same as CI
+python scripts/privacy.py . # privacy scan, same as CI
+```
+
+## CI
+
+- `check.yml`: on a PR it builds the whole site (dead-link check), checks that the Chinese and English pages match (`scripts/i18n.py`: every page exists in both languages, headings have the same levels and order, site links do not cross languages, and every anchor resolves; a page changed in one language only gets a warning), and runs the privacy scan.
+- `deploy.yml`: after a merge into `main` it builds the site and publishes it to GitHub Pages.
+- Third-party actions are always pinned to a full 40-character commit SHA; no `pull_request_target`, no self-hosted runners.
+
+## License
+
+The documentation is published under the Apache License 2.0; see [LICENSE](LICENSE). Copyright 2026 qiyinxi.
diff --git a/README.md b/README.md
index 5847dc7..e0458da 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,14 @@
# ModAVD 文档站
-[ModAVD(魔改 AVD)](https://github.com/ModAVD/ModAVD) 的文档站源码,发布在 。用 [VitePress](https://vitepress.dev/) 编译。
+**简体中文** | [English](README.en.md)
-- 页面是 `docs/` 下的 Markdown;导航和侧边栏在 `docs/.vitepress/config.mts`。
+
+
+[ModAVD(魔改 AVD)](https://github.com/ModAVD/ModAVD) 的文档站源码,发布在 (英文版在 )。用 [VitePress](https://vitepress.dev/) 编译。
+
+- 页面是 `docs/` 下的 Markdown,中文是主语言;英文页在 `docs/en/` 下,路径和中文页一一对应。导航和侧边栏在 `docs/.vitepress/config.mts`,两种语言用同一张页面表。
- 每页底部有「在 GitHub 上改这一页」,改完提 PR 就行。写法见站内的「参与开发 → 文档和本站」。
+- 改了一种语言的页面,在同一个 PR 里把另一种也改了;只会写一种语言的,在 PR 里说一声,由维护者补上。
## 本地预览
@@ -13,12 +18,13 @@
npm ci --ignore-scripts
npm run dev # 本地预览
npm run build # 编出 docs/.vitepress/dist,有死链会报错
+python scripts/i18n.py # 核对中英页面和标题,和 CI 一样
python scripts/privacy.py . # 隐私扫描,和 CI 一样
```
## CI
-- `check.yml`:PR 上编译整站(查死链)、跑隐私扫描。
+- `check.yml`:PR 上编译整站(查死链)、核对中英页面(`scripts/i18n.py`:每页都有两种语言,标题的层级和顺序相同,站内链接不串语言,锚点都找得到;只改了一种语言的页面会标出提醒)、跑隐私扫描。
- `deploy.yml`:合进 `main` 后编译并发布到 GitHub Pages。
- 第三方 action 一律钉到 40 位提交 SHA;不用 `pull_request_target`,不用自托管 runner。
diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts
index c76a5b3..f3683b7 100644
--- a/docs/.vitepress/config.mts
+++ b/docs/.vitepress/config.mts
@@ -1,110 +1,176 @@
-import { defineConfig } from 'vitepress'
+import { defineConfig, type DefaultTheme } from 'vitepress'
const repo = 'https://github.com/ModAVD/modavd.github.io'
+const origin = 'https://modavd.github.io'
+
+type Lang = 'zh' | 'en'
+
+// 页面标题,两种语言放在同一张表里:新加页面时两边一起写。
+// [链接, 中文标题, 英文标题]
+type Page = [link: string, zh: string, en: string]
+
+const guide: Page[] = [
+ ['/guide/', '这是什么', 'What is ModAVD'],
+ ['/guide/install', '安装', 'Install'],
+ ['/guide/upgrade', '升级', 'Upgrade'],
+ ['/guide/changes', '和官方模拟器有什么不同', 'How ModAVD differs from the official emulator'],
+ ['/guide/feedback', '反馈问题', 'Report a problem'],
+ ['/guide/privacy', '隐私', 'Privacy'],
+ ['/guide/license', '许可证与源码', 'Licenses and source code'],
+]
+
+const components: Page[] = [
+ ['/components/manager', '管理器和命令行', 'The manager and CLI'],
+ ['/components/bridge', 'arm64 执行桥', 'The arm64 execution bridge'],
+ ['/components/ime', '宿主输入法', 'The host IME'],
+]
+
+const develop: { group: [zh: string, en: string]; pages: Page[] }[] = [
+ {
+ group: ['开始', 'Getting started'],
+ pages: [
+ ['/develop/', '参与 ModAVD', 'Contributing to ModAVD'],
+ ['/develop/overview', '分区一览和通用要求', 'Areas and common requirements'],
+ ['/develop/ai', '用 AI 工具协助', 'Using AI tools'],
+ ],
+ },
+ {
+ group: ['各分区', 'Areas'],
+ pages: [
+ ['/develop/emulator', '模拟器本体', 'The emulator itself'],
+ ['/develop/build', '从源码构建', 'Building from source'],
+ ['/develop/bridge', 'arm64 执行桥', 'The arm64 execution bridge'],
+ ['/develop/manager', '管理器和命令行', 'The manager and CLI'],
+ ['/develop/ime', '宿主输入法', 'The host IME'],
+ ['/develop/package', '随包脚本', 'Bundled scripts'],
+ ['/develop/docs', '文档和本站', 'Documentation and this site'],
+ ['/develop/automas', 'AUTO-MAS 对接', 'AUTO-MAS integration'],
+ ['/develop/testing', '游戏实测和兼容性报告', 'Game testing and compatibility reports'],
+ ],
+ },
+ {
+ group: ['查问题', 'Investigating problems'],
+ pages: [
+ ['/develop/adapt-game', '适配新游戏', 'Adapting a new game'],
+ ['/develop/performance', '卡顿、掉帧怎么查', 'Investigating stutter and frame drops'],
+ ['/develop/troubleshooting', '常见问题怎么查', 'Investigating common problems'],
+ ],
+ },
+]
+
+const label = {
+ zh: {
+ guide: '使用', components: '组件', develop: '参与开发', download: '下载', fullPackage: 'ModAVD(整包)',
+ description: '基于 AOSP Android Emulator 的安卓模拟器',
+ },
+ en: {
+ guide: 'Guide', components: 'Components', develop: 'Contributing', download: 'Download', fullPackage: 'ModAVD (full package)',
+ description: 'An Android emulator built from the AOSP Android Emulator',
+ },
+}
+
+function nav(lang: Lang): DefaultTheme.NavItem[] {
+ const p = lang === 'en' ? '/en' : ''
+ const l = label[lang]
+ return [
+ { text: l.guide, link: `${p}/guide/`, activeMatch: `${p}/guide/` },
+ { text: l.components, link: `${p}/components/manager`, activeMatch: `${p}/components/` },
+ { text: l.develop, link: `${p}/develop/`, activeMatch: `${p}/develop/` },
+ {
+ text: l.download,
+ items: [
+ { text: l.fullPackage, link: 'https://github.com/ModAVD/ModAVD/releases' },
+ { text: 'ModAVDManager', link: 'https://github.com/ModAVD/ModAVDManager/releases' },
+ { text: 'ModAVDHostIME', link: 'https://github.com/ModAVD/ModAVDHostIME/releases' },
+ ],
+ },
+ ]
+}
+
+function sidebar(lang: Lang): DefaultTheme.Sidebar {
+ const p = lang === 'en' ? '/en' : ''
+ const items = (pages: Page[]) => pages.map(([link, zh, en]) => ({ text: lang === 'en' ? en : zh, link: p + link }))
+ const i = lang === 'en' ? 1 : 0
+ return {
+ [`${p}/guide/`]: [{ text: label[lang].guide, items: items(guide) }],
+ [`${p}/components/`]: [{ text: label[lang].components, items: items(components) }],
+ [`${p}/develop/`]: develop.map(({ group, pages }) => ({ text: group[i], items: items(pages) })),
+ }
+}
+
+// 指向同一页的另一种语言
+function alternates(relativePath: string): [string, Record][] {
+ if (!relativePath.endsWith('.md') || relativePath === '404.md') return []
+ const url = (path: string) => origin + '/' + path.replace(/\.md$/, '').replace(/(^|\/)index$/, '$1')
+ const zh = relativePath.replace(/^en\//, '')
+ return [
+ ['link', { rel: 'alternate', hreflang: 'zh-CN', href: url(zh) }],
+ ['link', { rel: 'alternate', hreflang: 'en', href: url('en/' + zh) }],
+ ]
+}
export default defineConfig({
- lang: 'zh-CN',
title: 'ModAVD',
- description: '基于 AOSP Android Emulator 的安卓模拟器',
cleanUrls: true,
lastUpdated: true,
// 不往外取字体、统计脚本,页面只用本站自己的文件
head: [['meta', { name: 'theme-color', content: '#3c6fb4' }]],
+ transformHead: ({ pageData }) => alternates(pageData.relativePath),
+ // 中文(根)和英文(/en/)各一份导航、侧边栏和界面文字,页面一一对应
locales: {
- root: { label: '简体中文', lang: 'zh-CN' },
+ root: {
+ label: '简体中文',
+ lang: 'zh-CN',
+ description: label.zh.description,
+ themeConfig: {
+ nav: nav('zh'),
+ sidebar: sidebar('zh'),
+ editLink: { pattern: `${repo}/edit/main/docs/:path`, text: '在 GitHub 上改这一页' },
+ footer: { message: 'Android 是 Google LLC 的商标。', copyright: '文档按 Apache License 2.0 发布' },
+ outline: { level: [2, 3], label: '本页内容' },
+ docFooter: { prev: '上一页', next: '下一页' },
+ lastUpdated: { text: '最后更新' },
+ returnToTopLabel: '回到顶部',
+ sidebarMenuLabel: '目录',
+ darkModeSwitchLabel: '深色模式',
+ lightModeSwitchTitle: '切换到浅色',
+ darkModeSwitchTitle: '切换到深色',
+ langMenuLabel: '语言',
+ notFound: { title: '页面不存在', quote: '这个地址没有页面,可能是改名或挪走了。', linkText: '回首页' },
+ },
+ },
en: {
label: 'English',
lang: 'en-US',
- description: 'An Android emulator built from the AOSP Android Emulator',
+ link: '/en/',
+ description: label.en.description,
themeConfig: {
- nav: [{ text: 'GitHub', link: 'https://github.com/ModAVD/ModAVD' }],
- sidebar: { '/en/': [{ text: 'English', items: [{ text: 'Overview', link: '/en/' }] }] },
+ nav: nav('en'),
+ sidebar: sidebar('en'),
+ editLink: { pattern: `${repo}/edit/main/docs/:path`, text: 'Edit this page on GitHub' },
+ footer: { message: 'Android is a trademark of Google LLC.', copyright: 'Documentation is published under the Apache License 2.0' },
+ outline: { level: [2, 3], label: 'On this page' },
+ docFooter: { prev: 'Previous page', next: 'Next page' },
+ lastUpdated: { text: 'Last updated' },
+ returnToTopLabel: 'Back to top',
+ sidebarMenuLabel: 'Menu',
+ darkModeSwitchLabel: 'Appearance',
+ lightModeSwitchTitle: 'Switch to light theme',
+ darkModeSwitchTitle: 'Switch to dark theme',
+ langMenuLabel: 'Language',
+ notFound: {
+ title: 'PAGE NOT FOUND',
+ quote: 'There is no page at this address; it may have been renamed or moved.',
+ linkText: 'Take me home',
+ },
},
},
},
themeConfig: {
- nav: [
- { text: '使用', link: '/guide/', activeMatch: '/guide/' },
- { text: '组件', link: '/components/manager', activeMatch: '/components/' },
- { text: '参与开发', link: '/develop/', activeMatch: '/develop/' },
- {
- text: '下载',
- items: [
- { text: 'ModAVD(整包)', link: 'https://github.com/ModAVD/ModAVD/releases' },
- { text: 'ModAVDManager', link: 'https://github.com/ModAVD/ModAVDManager/releases' },
- { text: 'ModAVDHostIME', link: 'https://github.com/ModAVD/ModAVDHostIME/releases' },
- ],
- },
- ],
-
- sidebar: {
- '/guide/': [
- {
- text: '使用',
- items: [
- { text: '这是什么', link: '/guide/' },
- { text: '安装', link: '/guide/install' },
- { text: '升级', link: '/guide/upgrade' },
- { text: '和官方模拟器有什么不同', link: '/guide/changes' },
- { text: '反馈问题', link: '/guide/feedback' },
- { text: '隐私', link: '/guide/privacy' },
- { text: '许可证与源码', link: '/guide/license' },
- ],
- },
- ],
- '/components/': [
- {
- text: '组件',
- items: [
- { text: '管理器和命令行', link: '/components/manager' },
- { text: 'arm64 执行桥', link: '/components/bridge' },
- { text: '宿主输入法', link: '/components/ime' },
- ],
- },
- ],
- '/develop/': [
- {
- text: '开始',
- items: [
- { text: '参与 ModAVD', link: '/develop/' },
- { text: '分区一览和通用要求', link: '/develop/overview' },
- { text: '用 AI 工具协助', link: '/develop/ai' },
- ],
- },
- {
- text: '各分区',
- items: [
- { text: '模拟器本体', link: '/develop/emulator' },
- { text: '从源码构建', link: '/develop/build' },
- { text: 'arm64 执行桥', link: '/develop/bridge' },
- { text: '管理器和命令行', link: '/develop/manager' },
- { text: '宿主输入法', link: '/develop/ime' },
- { text: '随包脚本', link: '/develop/package' },
- { text: '文档和本站', link: '/develop/docs' },
- { text: 'AUTO-MAS 对接', link: '/develop/automas' },
- { text: '游戏实测和兼容性报告', link: '/develop/testing' },
- ],
- },
- {
- text: '查问题',
- items: [
- { text: '适配新游戏', link: '/develop/adapt-game' },
- { text: '卡顿、掉帧怎么查', link: '/develop/performance' },
- { text: '常见问题怎么查', link: '/develop/troubleshooting' },
- ],
- },
- ],
- },
-
socialLinks: [{ icon: 'github', link: 'https://github.com/ModAVD' }],
- editLink: {
- pattern: `${repo}/edit/main/docs/:path`,
- text: '在 GitHub 上改这一页',
- },
-
search: {
provider: 'local',
options: {
@@ -122,21 +188,5 @@ export default defineConfig({
},
},
},
-
- footer: {
- message: 'Android 是 Google LLC 的商标。',
- copyright: '文档按 Apache License 2.0 发布',
- },
-
- outline: { level: [2, 3], label: '本页内容' },
- docFooter: { prev: '上一页', next: '下一页' },
- lastUpdated: { text: '最后更新' },
- returnToTopLabel: '回到顶部',
- sidebarMenuLabel: '目录',
- darkModeSwitchLabel: '深色模式',
- lightModeSwitchTitle: '切换到浅色',
- darkModeSwitchTitle: '切换到深色',
- langMenuLabel: '语言',
- notFound: { title: '页面不存在', quote: '这个地址没有页面,可能是改名或挪走了。', linkText: '回首页' },
},
})
diff --git a/docs/develop/docs.md b/docs/develop/docs.md
index a5a4a84..1ddd8f9 100644
--- a/docs/develop/docs.md
+++ b/docs/develop/docs.md
@@ -5,7 +5,7 @@
| 内容 | 在哪改 |
|---|---|
| 本站(使用说明、组件介绍、参与开发) | [modavd.github.io](https://github.com/ModAVD/modavd.github.io) 仓库的 `docs/` |
-| 各仓库自己的 README、`CONTRIBUTING.md` | 各自的仓库 |
+| 各仓库自己的 README(中文 `README.md`、英文 `README.en.md`)、`CONTRIBUTING.md` | 各自的仓库 |
| 发版说明、补丁说明(`release/`、`patches/BASE.md`)、仓库清单 | ModAVD 仓库,由发版工具导出,**不要手改**,有问题先开 issue |
每页底部有「在 GitHub 上改这一页」,点进去直接改、提 PR 就行。
@@ -18,9 +18,10 @@
npm ci --ignore-scripts
npm run dev # 本地预览,改了自动刷新
npm run build # 编出静态页面,有死链会报错
+python scripts/i18n.py # 核对中英两边的页面和标题
```
-- 页面是 `docs/` 下的 Markdown,侧边栏和导航在 `docs/.vitepress/config.mts`。新加页面要在那里挂上。
+- 页面是 `docs/` 下的 Markdown,英文页在 `docs/en/` 下,路径和中文页一一对应。侧边栏和导航在 `docs/.vitepress/config.mts`,两种语言各一份,新加页面要在两边都挂上。
- 提示框用 `::: tip`、`::: warning`、`::: danger`、`::: info`。
- 站内链接写相对路径、不带 `.md`,例如 `[安装](../guide/install)`;链到别的仓库的文件写完整的 GitHub 地址。
- 不加统计脚本、不从别的网站取字体或图片。
@@ -31,13 +32,15 @@ npm run build # 编出静态页面,有死链会报错
PR 上的 CI 会:
- 编译整站,有死链就失败;
+- 核对中英两边(`python scripts/i18n.py`):每页都有两种语言,标题的层级和顺序相同,站内链接不串到另一种语言,`#锚点` 都找得到;只改了一种语言的页面会标出提醒;
- 跑隐私扫描(`python scripts/privacy.py .`),文档里出现本机用户目录这类路径就失败。
合进 `main` 以后自动发布到 GitHub Pages。
## 写法
-- 中文,短句,写用户看得懂的说法。
+- 中文是主语言,英文页逐页对应。改了中文页,在同一个 PR 里把对应的英文页也改了;不会写英文的,在 PR 里说一声,由维护者补上。
+- 中文,短句,写用户看得懂的说法。英文照意思写成自然的英文,不逐字硬译。
- 写清楚是哪个版本起有的、哪个版本起变的。
- 能用表格、列表的就别写成大段。
- 命令写完整、能直接复制,路径用 `<占位符>` 标出要换的部分。
diff --git a/docs/en/components/bridge.md b/docs/en/components/bridge.md
new file mode 100644
index 0000000..6db2805
--- /dev/null
+++ b/docs/en/components/bridge.md
@@ -0,0 +1,38 @@
+# The arm64 execution bridge
+
+It lets games that only have an arm64 build and use app hardening run on ModAVD's x86_64 system image. Right now it takes effect only for the 7 channel builds of *Onmyoji*. From 0.36.0 it ships with the main Release package, installed in `sdk\emulator\resources\modavd\`.
+
+::: info It does not touch the game
+The bridge **does not modify, patch or bypass the game or its hardening libraries, and does not interfere with any integrity or anti-tamper check**. This is compatibility work on the translation layer: it makes the hooks the game installs itself execute and return correctly. Intel Houdini already works this way, and the same game runs on Houdini. We do not change a single byte of Google's translation-layer binaries.
+:::
+
+## Why it is needed
+
+x86_64 images run arm64 apps through Google's translation layer: the system libraries stay native x86_64, and only the arm64 libraries that ship with the app are translated.
+
+A game's hardening library redirects the entry points of some functions in the system libraries to its own arm64 code. On a real device both sides are arm64, so this is fine. On an x86_64 image, the native code crashes as soon as it jumps into arm64 code, because the translation layer only supports translated code calling native code, not the other way round. The bridge fills this gap using the interfaces the translation layer itself exports. For the details, see [Develop: the arm64 execution bridge](../develop/bridge).
+
+## Only for games on the list
+
+- The list is currently the 7 channel builds of *Onmyoji*.
+- For apps not on the list, after the process starts, everything the bridge changed is reverted, so they behave the same as when the bridge is not installed.
+
+## Installing into an instance
+
+- **From 0.36.0 you do not need to install it yourself**: when you start an instance with the manager `ModAVD.exe` or the CLI `tools\modavd.exe start`, both new and existing instances get the bridge automatically. If the bridge is not installed after the startup sequence finishes, it is installed; if it does not take effect, the instance is shut down and cold-booted, up to three rounds. The first boot takes 1–2 minutes longer.
+- Once it is installed, start instances with AUTO-MAS as usual; the bridge stays in place.
+- An instance that has only ever been started by AUTO-MAS and never by the manager is not installed automatically in this version: start it once with the manager.
+- The bridge is installed in the instance's own system / vendor overlay and does not touch Google's original image.
+
+## If you do not want the bridge
+
+- When creating an instance, use `tools\modavd.exe create --no-bridge`;
+- For an existing instance, run `tools\modavd.exe bridge uninstall`; after that, starts no longer install it automatically (run `install` again to restore it);
+- `start --no-bridge` applies to that one start only;
+- For a read-only check, use `bridge verify` (the instance must be running).
+
+::: warning Before rolling back to an older version
+Before going back to a version earlier than 0.36.0, run `tools\modavd.exe bridge uninstall` once on every instance, and swap the package only after the result says the bridge is not installed. If you roll back without uninstalling first, every app on that instance that only has an arm64 build will fail to run.
+:::
+
+The source is in the [`bridge/`](https://github.com/ModAVD/ModAVD/tree/main/bridge) folder of the ModAVD repository, released under AGPL-3.0-or-later.
diff --git a/docs/en/components/ime.md b/docs/en/components/ime.md
new file mode 100644
index 0000000..2bb0f8f
--- /dev/null
+++ b/docs/en/components/ime.md
@@ -0,0 +1,30 @@
+# The host IME
+
+A headless input method, `org.modavd.ime`, installed in the emulator's Android. Its source is in [ModAVDHostIME](https://github.com/ModAVD/ModAVDHostIME).
+
+When you use the emulator with a window, it lets you type into Android directly with the Windows IME: Chinese, AltGr combinations and dead keys all work. Automation scripts can also type text in any language with the emulator console's `ime commit `.
+
+- It shows no input interface. Physical keys and `adb shell input` injection still go straight to the app, so games and automation are not affected.
+- It requests no permissions, stores no data, and does not log the text that is typed.
+- It needs an emulator from ModAVD 0.35.0 or newer (the `modavd_ime` channel exists from this version) and Android 11 or later. On an older emulator, installing it is harmless: it only backs off and retries the connection in the background and does not crash.
+
+## How it gets installed
+
+From 0.36.0 the package includes `components\modavd-ime.apk`, which is handled automatically when you start with the manager or the CLI:
+
+- It is installed when it is not installed yet, when the installed version is older than the one in the package, or when the version number is the same but the content differs. It is never downgraded;
+- After a fresh install it is enabled, and the decision whether to make it the default input method is made only once: it becomes the default only if the default at that time is still the image's own keyboard (or none). After that, if you switch to another input method, it is not changed back.
+
+If you use a ModAVD release package, you do not need to install it manually.
+
+## Signing certificate of the official APK
+
+- Certificate SHA-256: `d18cca3c1982149349f164d28e02490b2eb694e44d56834fa02a1062eb42e823`
+- Certificate subject `CN=ModAVD`, RSA 4096.
+- To verify: `apksigner verify --print-certs `. The `certificate SHA-256 digest` in the output must match the value above.
+
+## Downloading separately
+
+The IME has its own version number (from v1.0.0) and is released separately on [ModAVDHostIME Releases](https://github.com/ModAVD/ModAVDHostIME/releases). The `components\modavd-ime.apk` in v1.0.0 and in the ModAVD 0.36.0 package is byte-for-byte identical.
+
+An APK you build yourself is signed with your own key. To keep using it, its `versionCode` must be higher than the one in the release package; otherwise the manager switches back to the official version at boot. See [Develop: the host IME](../develop/ime).
diff --git a/docs/en/components/manager.md b/docs/en/components/manager.md
new file mode 100644
index 0000000..0475e6b
--- /dev/null
+++ b/docs/en/components/manager.md
@@ -0,0 +1,74 @@
+# The manager and CLI
+
+Since ModAVD 0.36.0 the package includes two management programs. Their source is in [ModAVDManager](https://github.com/ModAVD/ModAVDManager):
+
+| Program | Location | Who uses it |
+|---|---|---|
+| The manager `ModAVD.exe` | Package root | People: instance cards, start and stop, create, settings, screen view, logs |
+| The CLI `modavd.exe` | `tools\` | Scripts, AUTO-MAS and AI assistants; `modavd mcp` is an MCP server |
+
+Instance files and `mas-avd.json` are written the same way as in AUTO-MAS, so instances created by either one can be started by the other.
+
+## The manager
+
+Double-click `ModAVD.exe` in the package root. It starts a local server that listens only on 127.0.0.1, then opens a window in Edge app mode (Edge comes with Windows 10 / 11); if Edge is not found, it uses the default browser. The page is embedded in the program and does not use the network.
+
+- Features: instance cards (with a screen thumbnail when the instance is online), start and stop (with progress), create, settings, delete, PC check, activity panel, screen view (a click is a tap; Back / Home / Recents), logs, install APK, open folder; light / dark / follow system.
+- One server runs per root folder; double-clicking again only reopens the window. The log is at `\logs\modavd-ui.log`.
+- After you close the window, it waits for the running tasks to finish before it exits.
+
+## The CLI
+
+```
+modavd [--root ] [--json] [--quiet] [--verbose] [args]
+```
+
+| Command | Description |
+| --- | --- |
+| `list` | All instances and their status |
+| `info ` / `status ` | Detailed information / status of one instance |
+| `create [--index N] [--title T] [--memory 6G] [--cpu N] [--data-gb N] [--fps 30\|60] [--no-bridge]` | Create an instance. It includes the arm64 execution bridge by default, installed on the first boot |
+| `set [--title T] [--memory M] [--cpu N] [--fps F] [--data-gb N]` | Change settings; they take effect on the next start. `--data-gb` can only grow the disk; game data is untouched |
+| `delete --yes` | Delete a shut-down instance together with its game data |
+| `start [--window] [--timeout 300] [--no-bridge]` | Start, then wait until boot is complete and the post-boot setup is done |
+| `stop [--force]`, `stop --all` | Shut down: first ask Android for a clean shutdown; if that fails, sync + kill. `--force` is sync + force-kill |
+| `restart [--window] [--timeout 300] [--force] [--no-bridge]` | Shut down, then start |
+| `bridge install\|uninstall\|verify` | Install, uninstall or check the arm64 execution bridge |
+| `check [--memory M]` | PC check before starting |
+| `window show\|hide`, `install `, `shell `, `adb -- ` | Window, install an APK, guest command, adb passthrough |
+| `servers`, `version`, `mcp`, `help [command]` | |
+
+- Write `` as `3` or `mas_3` (0–9, except 5). Write memory as `6144`, `6144M` or `6G`; there are only four levels: 3 / 4 / 5 / 6 GB. Cores are 2 / 4 / 6, frame rate 30 / 60.
+- Root folder: `--root`; if it is not given, the environment variable `MODAVD_ROOT`; otherwise the folder containing `modavd.exe` or its parent.
+- adb uses only the root folder's private server (`adbServerPort` in `mas-avd.json`) and never touches the default 5037.
+- Shutdown syncs first and then stops, so it does not leave 0-byte files behind.
+
+For machine-readable output (`--json`), exit codes and the full option reference, see [the ModAVDManager README](https://github.com/ModAVD/ModAVDManager/blob/main/README.en.md#command-line).
+
+## MCP
+
+```
+modavd mcp --root D:\ModAVD
+```
+
+Tools: `list_instances`, `get_instance`, `check_host`, `create_instance`, `update_instance`, `delete_instance`, `start_instance` (with progress), `stop_instance`, `set_window_visible`, `shell`, `install_apk`.
+
+To register it in Claude Code (in PowerShell, `--` must be quoted, or it gets swallowed):
+
+```powershell
+claude mcp add --transport stdio --scope user modavd '--' D:\ModAVD\tools\modavd.exe mcp --root D:\ModAVD
+```
+
+Or in a project's `.mcp.json`:
+
+```json
+{"mcpServers": {"modavd": {"command": "D:\\ModAVD\\tools\\modavd.exe", "args": ["mcp", "--root", "D:\\ModAVD"]}}}
+```
+
+## Downloading separately
+
+The manager has its own version number (from v0.1.0) and is released separately on [ModAVDManager Releases](https://github.com/ModAVD/ModAVDManager/releases).
+
+- Normally just use the copy that comes in the ModAVD package; it is replaced together with the package when you upgrade.
+- A separately downloaded package can go in any folder; point it at the ModAVD root folder with `--root` or `MODAVD_ROOT`. Do not extract it into the ModAVD root folder and overwrite the files from the package.
+- After downloading, check the hash against `SHA256SUMS.txt` in the release.
diff --git a/docs/en/develop/adapt-game.md b/docs/en/develop/adapt-game.md
new file mode 100644
index 0000000..f2f6171
--- /dev/null
+++ b/docs/en/develop/adapt-game.md
@@ -0,0 +1,67 @@
+# Adapting a new game
+
+To get a game that currently will not start or runs badly working on ModAVD, work in the order below. Adaptation has no separate code folder: after you find the cause, the change lands in one place, either the execution bridge, the emulator itself or the automation script. Specific cases investigated before are in [How to investigate common problems](./troubleshooting).
+
+## Preparation
+
+- Use the latest ModAVD, create a new dedicated instance, and log in with a test account. Adapting a game means installing, uninstalling and force-killing over and over, so do not use the instance you normally use to run games unattended. Old versions lack a lot; for example, 0.32 does not have the arm64 execution bridge yet.
+- For adb, use the private port from `mas-avd.json`: `adb -P -s emulator- ...`. Commands below that need root are written as `shell su 0 `.
+- The hardware is the same as for [testing on real games](./testing#hardware), plus disk space for this game.
+
+## Step 1: Find out about the game {#step1}
+
+- Package name, channel (official server, Bilibili server, the various app stores) and game version. Find the package name with `shell pm list packages | findstr `.
+- Whether it is arm64-only: `shell dumpsys package | findstr primaryCpuAbi`. `arm64-v8a` has to go through translation; `x86_64` or `x86` runs natively.
+- Whether it uses app hardening or anti-cheat: unpack the APK and look at the library names under `lib/`.
+- Whether an automation script already exists (the MAA series, M9A, SRC and the like). This decides whether the game can enter the pre-release regression tests later.
+
+## Step 2: Reproduce and collect evidence {#step2}
+
+- Before launching, run `logcat -c`, then `logcat -b all -v threadtime > 启动.txt`, then launch the game, and stop once it reproduces.
+- If it crashed, take the newest file in `/data/tombstones/`: `shell su 0 ls -t /data/tombstones`.
+- The emulator logs are in `logs\` in the root folder. `收集问题信息.bat` (collects a problem report) packs the logs together.
+- Look mainly at these:
+ - `Fatal signal`: which library and which thread it crashed in;
+ - `FATAL EXCEPTION`;
+ - `ANR in`;
+ - `VK_ERROR` and `DEVICE_LOST` in the emulator log.
+- Note exactly which step it gets stuck on, and whether it happens every time or only sometimes.
+
+## Step 3: Find what can be changed, by cause {#step3}
+
+Try approaches that need no recompiling first, and settle the direction before you touch code.
+
+| Cause | Try first (no recompiling) | Where to change it if you really have to |
+|---|---|---|
+| arm64-only; crashes in the translation layer or exits right after launch | Make the execution bridge take effect for it temporarily: first make sure the instance has the bridge installed, then run `shell su 0 setprop modavd.gate.target `, then cold-start the game. This property replaces the whole list, is not persistent, and is gone when the guest restarts. Check logcat for `shim-ctor OK` and whether the game gets through | If it gets through: send a PR that adds the package name to `kDefaultGateTargets` in `bridge/companion/jni/native_to_guest_companion.cc`. If it still fails: this is the deep end of the translation layer and the bridge; open an issue with the tombstone and the launch logcat |
+| Graphics: black screen, garbled picture, Vulkan errors, device lost | Two environment-variable switches that are off by default (`ANDROID_EMU_VK_HIDE_REBAR=1`, `ANDROID_EMU_VK_ASTC_BC3=1`; see [How ModAVD differs from the official emulator](../guide/changes#graphics)); change the resolution (two levels, 720p / 1080p); while investigating, you can uninstall the bridge with `modavd bridge uninstall` to compare, and uninstalling the bridge restores the GL transport to what it was | The emulator's gfxstream patches; see [the emulator itself](./emulator) |
+| Stutter and frame drops | Use [How to investigate stutter and frame drops](./performance) to find out which thread and which stage the bottleneck is in; then compare a few existing switches: GL transport asg / pipe, `ANDROID_EMU_VK_HIDE_REBAR=1`, and the Vulkan feature flags | If the bottleneck is the graphics round trip: change the emulator's gfxstream. If it is in translation: open an issue to discuss it. If it is in the game's own main thread: accept it, or lower the quality |
+| The game detects the emulator or root, or kicks you out after you enter the game | — | Do not do anything. ModAVD does not bypass the game's protection and does not change game files. Note the exact message text and open an issue describing the situation |
+| Network request timeout, hot update fails | Switch networks; check the game's data folder for 0-byte files (left behind by a hard kill) | Usually not something to change in ModAVD |
+| The game runs, but the automation script cannot recognize the screen or taps inaccurately | Check the script's screenshot method, input method and resolution settings | Change it on the script side (for example, add a resource overlay for ModAVD to it), not in ModAVD |
+
+## Step 4: Delivery {#step4}
+
+- First open an issue titled "Adapt: \ (\)", describing what you found in the first three steps and how you plan to change it.
+- Adding to the bridge list: the PR changes only `kDefaultGateTargets` and comes with this evidence:
+ - the launch logcat before and after adding to the list;
+ - a game that was already on the list (*Onmyoji*) still works as usual;
+ - a game not on the list still works as usual, and the log has the line saying the changes were reverted.
+
+ The maintainer rebuilds the payload and pins its hash; it ships with the next version.
+- Graphics changes: submit patches as described in [the emulator itself](./emulator#patches).
+- You are not asked to run the full set of regression tests; the maintainer builds and tests on their own machine.
+
+## Step 5: After it works {#after}
+
+- Add a note in the pinned "兼容性报告" (compatibility report) issue: the game, channel, version, how you got it running, and roughly what frame rate it gets.
+- If the game has an automation script and tasks that do not use many resources, the maintainer will add it to the pre-release regression tests and record a frame-rate baseline.
+
+## Rules
+
+Use a test account; do not modify game files or bypass the game's protection; do not pull gacha or buy anything; stop when you hit an update prompt; sync before you shut down the emulator.
+
+## Suggested models
+
+- Steps 1 and 2, and the classification in step 3 (reading logcat and the emulator logs): Sonnet 5.5 or GPT-6.1 Sol;
+- Finding the root cause in the translation layer, the bridge or graphics problems: Opus 5.5 or GPT-6 Astra, with reasoning set high.
diff --git a/docs/en/develop/ai.md b/docs/en/develop/ai.md
new file mode 100644
index 0000000..9a5c5ff
--- /dev/null
+++ b/docs/en/develop/ai.md
@@ -0,0 +1,27 @@
+# Using AI tools
+
+You can use AI tools to write code and investigate problems. There are only two rules:
+
+- **Have the AI test its own changes**: compile, run the unit tests, and if you can start an instance, start one and look at the result. State in the PR what you tested and what the result was.
+- **Do not give accounts, keys or private paths to AI tools.**
+
+## Choosing a model by task
+
+| Task | Claude | GPT (Codex) |
+|---|---|---|
+| The emulator itself, the execution bridge, root causes of crashes | Opus 5.5, reasoning set high | GPT-6 Astra, High or Extra High |
+| Ordinary features and UI of the manager, the IME, CI, scripts | Sonnet 5.5 | GPT-6.1 Sol, Medium |
+| Anything security-related, such as package updates, signing, release workflows and permissions | Sonnet 5.5 writes, Opus 5.5 reviews, a person reviews last | GPT-6.1 Sol writes, GPT-6 Astra reviews, a person reviews last |
+| Running tests, reading logs, watching progress, writing docs | Sonnet 5.5 | GPT-6.1 Terra |
+| Tidying logs, bulk reformatting, checking lists | Haiku 5.5 | GPT-6 Luna |
+| Review before merging a PR | Opus 5.5, not the same session that wrote the code | GPT-6 Astra, likewise not the same session that wrote the code |
+
+- Model names are as of October 2026. Both vendors update quickly; after a new generation, choose by the same tiers: give hard work to the strongest model with reasoning set high; give work with clear rules to a mid-tier model; give pure shuffling to a cheap model.
+- On the GPT side, GPT-6.1 Sol is close to Astra and a good deal cheaper, which suits long coding sessions; when the budget is tight, the emulator itself and the bridge can also use Sol with Extra High.
+- More specific advice for each area is in [Areas](./overview) and in the "Suggested models" section of each area's page.
+
+## Prompting the AI
+
+- Tell it the rules to follow directly: sync before you shut down the emulator; use the private port for adb and never touch 5037; do not change game files or bypass the game's protection; do not pull gacha or buy anything in the game.
+- Have it gather evidence before it draws conclusions. The misjudgments in the past (taking a fork deadlock for a slow network, taking files damaged by a hard kill for a CDN that could not be reached) all came from guessing without looking at the actual scene. See [How to investigate common problems](./troubleshooting).
+- When comparing performance, have it run alternating rounds; a single run of each does not count.
diff --git a/docs/en/develop/automas.md b/docs/en/develop/automas.md
new file mode 100644
index 0000000..fcee584
--- /dev/null
+++ b/docs/en/develop/automas.md
@@ -0,0 +1,31 @@
+# AUTO-MAS integration
+
+**What to change**: the part of [AUTO-MAS](https://github.com/AUTO-MAS-Project/AUTO-MAS) that manages ModAVD instances (creating instances, start and stop, updating the package). It is planned to change from AUTO-MAS's own Python implementation to calling the `modavd` CLI. The change goes to the AUTO-MAS repository, and AUTO-MAS's maintainers decide whether to accept it.
+
+## Environment
+
+Follow AUTO-MAS's own development guidelines (Python environment, generated frontend files, test requirements).
+
+## Hardware
+
+In addition to AUTO-MAS's own development environment. If you need to start instances, it is best to also install a game for real runs.
+
+| | Recommended | Minimum |
+|---|---|---|
+| CPU | 8 cores, 16 threads | 4 cores, 8 threads |
+| Memory | 32 GB | 16 GB |
+| Free disk space | 100 GB | 50 GB |
+
+## Integration points
+
+- stdout is a single line of JSON and the log goes to stderr; collect the two separately;
+- go by `error.code`;
+- the first boot installs the execution bridge and restarts one or two more times, so allow a longer time limit;
+- shut down with `modavd stop`, which syncs first and then stops;
+- adb uses only the root folder's private server and never touches 5037.
+
+The contract for the commands and the machine-readable output is in [the ModAVDManager README](https://github.com/ModAVD/ModAVDManager/blob/main/README.en.md#command-line).
+
+## Suggested models
+
+Sonnet 5.5 or GPT-6.1 Sol writes; for subprocesses, time limits and mutual exclusion during updates, Opus 5.5 or GPT-6 Astra reviews.
diff --git a/docs/en/develop/bridge.md b/docs/en/develop/bridge.md
new file mode 100644
index 0000000..78f5ea7
--- /dev/null
+++ b/docs/en/develop/bridge.md
@@ -0,0 +1,87 @@
+# The arm64 execution bridge
+
+**What to change**: the layer that lets games that only have an arm64 build (currently the 7 channel builds of *Onmyoji*) run on the x86_64 image. It is in the [`bridge/`](https://github.com/ModAVD/ModAVD/tree/main/bridge) folder of the ModAVD repository:
+
+| Directory | Output | What it does |
+| --- | --- | --- |
+| `nbshim/` | `libmodavd_bridge.so` | Our own native bridge entry. `ro.dalvik.vm.native.bridge` points to it; `libnativebridge` opens it and gets `NativeBridgeItf`. It opens the real translation layer, copies the real struct over byte by byte at the length for its version (v6 = 144, v7 = 160, v8 = 168 bytes), forwards the calls one by one, and brings up the companion library |
+| `companion/` | `libmodavd_gate.so` | The bridge itself. Using the interfaces the translation layer exports itself (`WrapGuestFunctionImpl`, `RunGuestCall`, `GuestMapShadow`, `MakeTrampolineCallable`), it adds from the outside the path "native x86 code calls a translated arm64 function through a rewritten GOT slot" |
+| `nbshim/modavd_bridge.rc` | — | Re-registers the arm64 `binfmt_misc` for the new property value (the one that comes with the image only recognizes `libndk_translation.so`; once the property is changed, arm64 executables silently stop running); on instances that have been remounted, it loads zram at boot |
+
+Two generations of the translation layer are supported: ndk_translation 0.2.3 on the API 34 image (this is the one ModAVD uses) and Berberis 16 on API 36.1. Symbols are resolved by name from the images that are already mapped, and are not tied to a build-id.
+
+::: danger Hard rules
+Do not modify, patch or bypass any file of the game itself or of its protection libraries, and do not interfere with any integrity or anti-tamper check. Not a single byte of Google's translation-layer binaries is changed.
+:::
+
+## Why it crashes
+
+Google's native bridge keeps ART and the system libraries native x86_64 and translates only the app's own arm64 libraries, so one process is split into two halves.
+
+To watch dex reads, the game's hardening library (arm64, translated) makes the GNU_RELRO of the host `libartbase.so` writable, rewrites the GOT slots of functions such as `read` / `mmap` to point to its own arm64 hooks, and then makes it read-only again. On a real device both sides are arm64, and everything works up to this point.
+
+On an x86_64 image, the native x86 ART runs `call [GOT slot]` and jumps into an arm64 code page. The translation layer maps guest code pages as non-executable on the host side, so the instruction fetch faults (`SIGSEGV`, `SEGV_ACCERR`, and the fault address is RIP). The translation layer's own signal handler has no branch for "native code jumped into a guest page" and treats it as a fatal error.
+
+## Only for apps on the list
+
+- The list is comma-separated package names, compiled into the companion library (`kDefaultGateTargets` in `companion/jni/native_to_guest_companion.cc`).
+- If the property `modavd.gate.target` is set, it replaces the whole list; `setprop modavd.gate.target none` turns it off. The property is not persistent and is gone when the guest restarts, which suits trying out a new game temporarily (see [Adapting a new game](./adapt-game)).
+- For apps not on the list, after the process is forked, the forwarding callbacks and the slots the companion library changed are all reverted, so they behave the same as when the bridge is not installed.
+
+## Signal order
+
+The bridge works through SIGSEGV: the instruction-fetch fault raised when native code jumps into a guest page through a rewritten GOT slot is the bridge's entry point. This fault must reach us first, or another handler will treat it as a real crash, for example WebView's crashpad.
+
+The shim hands the companion library's decision function to ART through `getSignalHandler(SIGSEGV)` of the native bridge interface. ART registers it with libsigchain as a special handler, placed before all `sigaction()` handlers. It recognizes only our own trap and lets everything else through.
+
+## Environment and hardware
+
+- Android NDK r27c, about 2.2 GB; if you only compile, 4 cores and 8 GB of memory are enough.
+- The build is deterministic: the same source built in different folders gives outputs that differ only in the build-id.
+
+Verification needs a running instance with *Onmyoji* installed (6 GB of memory and 6 cores for testing; the instance is about 26 GB):
+
+| | Recommended | Minimum |
+|---|---|---|
+| CPU | 8 cores, 16 threads | 6 cores, 12 threads (the instance gets 6 cores); 4 cores, 8 threads also works, but the instance can only get 4 cores and the frame rate is lower |
+| Memory | 32 GB | 16 GB |
+| Free disk space | 50 GB | 35 GB |
+
+## Build
+
+```powershell
+$env:ANDROID_NDK_ROOT = ''
+pwsh -File bridge\scripts\build-companion.ps1 [-OutDir ]
+pwsh -File bridge\scripts\build-nbshim.ps1 [-OutDir ]
+```
+
+- The outputs go under `%TEMP%\modavd-nbbridge\` by default.
+- **Never add `-ftls-model=initial-exec`.** Both libraries are loaded with dlopen. A library with initial-exec TLS relocations is rejected by Bionic's linker, the whole native bridge fails to load, and the device loses all arm64 support. `build-nbshim.ps1` checks after building and reports an error if there are such relocations.
+- The same source built in different folders differs only in `.note.gnu.build-id` (the build-id contains the source path); with that section removed, the outputs are byte-identical. So it is normal that the hash of your own build does not match the one in the Release; the SHA-256 of the three files in the Release is written in `modavd-manifest.json` in the root of the main package.
+
+## Installing into an instance
+
+What does the work is `tools\modavd-bridge.ps1` in the package (its source is in `package/` in the ModAVD repository); the `bridge` command of the manager and the CLI both call it:
+
+- The instance must boot with a writable system image. The emulator from 0.36.0 does this when it sees the boot marker `modavd-writable-system` in the instance folder.
+- The two `.so` files go into `/system/lib64` (the shim has to be there: `libnativebridge` opens it in the linker's "system" namespace), and the `.rc` goes into `/system/etc/init/`.
+- Append `ro.dalvik.vm.native.bridge=libmodavd_bridge.so` to `/vendor/build.prop`. Back it up before changing it; check it after writing and before rebooting; run `sync` before rebooting.
+- Install in the order files first, property last; uninstall in the order property first, then files. The property is the only switch.
+- All of this is written to the instance's own system / vendor overlay and does not touch Google's original image.
+- When the guest needs a restart, always shut down and cold boot; do not hot-restart inside the guest (a hot restart hangs on WHPX, see [How to investigate common problems](./troubleshooting#system-level)).
+
+For how users install and uninstall the bridge, see [Components: the arm64 execution bridge](../components/bridge).
+
+## Verification
+
+- You need a logged-in instance with a game on the list installed; install the bridge with the manager or `modavd bridge install`;
+- Check logcat for `shim-ctor OK`; for a game not on the list, the log must have the line saying the changes were reverted;
+- Every version must be run on real games.
+
+## Delivery
+
+Open an issue first to discuss the change. It directly affects whether games can start. The maintainer rebuilds the payload and pins its hash; it ships with the next version.
+
+## Suggested models
+
+Opus 5.5 or GPT-6 Astra. With native code, the ABI, the dynamic linker and GOT rewriting, one mistake means the game will not start, and it also touches the hard rules above.
diff --git a/docs/en/develop/build.md b/docs/en/develop/build.md
new file mode 100644
index 0000000..fbe6c62
--- /dev/null
+++ b/docs/en/develop/build.md
@@ -0,0 +1,137 @@
+# Building from source
+
+The examples below use `0.36.0` (build number mas-36). For other versions, use that version's repository manifests and patches; do not mix source and binaries from different versions.
+
+The matching source bundle is in the [0.36.0 Release](https://github.com/ModAVD/ModAVD/releases/tag/v0.36.0). Its `SOURCES.txt` explains where each source file comes from and what it is for. From 0.32.1 the version is written `0..