From 069436daf6dc10e9ec4ab8a2eea4a5d045d9620d Mon Sep 17 00:00:00 2001 From: qiyinxi Date: Thu, 12 Nov 2026 22:46:32 +0100 Subject: [PATCH 1/3] =?UTF-8?q?=E7=89=88=E6=9C=AC=E5=8F=B7=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=200.9.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit go generate ./cmd/modavd-gui 重新生成两份 syso,exe 文件属性里的版本号跟着变。 --- cmd/modavd-gui/rsrc_windows_amd64.syso | Bin 73388 -> 73388 bytes internal/buildinfo/buildinfo.go | 2 +- rsrc_windows_amd64.syso | Bin 73420 -> 73420 bytes 3 files changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/modavd-gui/rsrc_windows_amd64.syso b/cmd/modavd-gui/rsrc_windows_amd64.syso index 0d42ad3f0086bfd8e5d01e260646ba876e500cf5..6c33eef5050957adcc8710c4267a1a617860cb55 100644 GIT binary patch delta 42 scmZ3pmu1afmWC~iJz|`k3=qIMeX1DaZ$``Q6U7;o8G-ax3C8cN00I*Wga7~l delta 42 scmZ3pmu1afmWC~iJz|_33=qIEeX1DaZ$^vl6U7;o8G-ax3C8cN00GGhfB*mh diff --git a/internal/buildinfo/buildinfo.go b/internal/buildinfo/buildinfo.go index 0009b84..1ae633d 100644 --- a/internal/buildinfo/buildinfo.go +++ b/internal/buildinfo/buildinfo.go @@ -4,7 +4,7 @@ package buildinfo // Version of modavd itself, kept in the source rather than set with -ldflags -X: release builds must come out byte // for byte the same for the same source (Mirror 酱 ships per-file deltas, and a version stamped per package would // change the exe in every release). The ModAVD package version comes from the root at run time. -var Version = "0.8.0" +var Version = "0.9.0" // Protocol is the version of the machine-readable contract: the commands, the JSON written by `--json`, the exit codes // and the MCP tool schemas. Callers such as AUTO-MAS check it (`modavd version --json`) before relying on a field. diff --git a/rsrc_windows_amd64.syso b/rsrc_windows_amd64.syso index 029beb4d2e6c8f9f3038da84409c091bccbd58fb..555b9cb6da54464fd4557293bf73af8da6163d99 100644 GIT binary patch delta 43 qcmX@Jm*vb}mWC~iJz|`k3=qJ%eX1CvG9#nq_MPGo`mO}ydsYAm-wRa$ delta 43 qcmX@Jm*vb}mWC~iJz|_33=qJveX1CvG9#nK_MPGo`mO}ydsYAmlM7J* From a33bbf45e859f4fcfa211c6755877c130fac4ec1 Mon Sep 17 00:00:00 2001 From: qiyinxi <52456734+qiyinxi@users.noreply.github.com> Date: Thu, 12 Nov 2026 21:54:26 +0000 Subject: [PATCH 2/3] =?UTF-8?q?=E5=AE=9E=E4=BE=8B=E5=8D=A1=E7=89=87?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E6=95=B0=E6=8D=AE=E7=9B=98=E5=AE=9E=E9=99=85?= =?UTF-8?q?=E5=8D=A0=E7=9A=84=E7=94=B5=E8=84=91=E7=A1=AC=E7=9B=98=20(#140)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 规格行末尾加「占 12.3 GB」:数据盘文件在电脑上现在实际占的大小(data_space.host_bytes,只算写进去的),读不到就不写。 --- .github/workflows/ci.yml | 2 +- internal/ui/web/js/cards.js | 4 ++-- internal/ui/web/js/format.js | 10 ++++++---- scripts/test_card_cfg.mjs | 20 ++++++++++++++++++++ 4 files changed, 29 insertions(+), 7 deletions(-) create mode 100644 scripts/test_card_cfg.mjs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3fdb188..ae97a9a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,7 +43,7 @@ jobs: - name: display coordinate tests run: node --test scripts/test_display_tap.mjs - name: disk UI tests - run: node --test scripts/test_disk_info.mjs scripts/test_compact_format.mjs + run: node --test scripts/test_disk_info.mjs scripts/test_compact_format.mjs scripts/test_card_cfg.mjs - name: gofmt shell: pwsh run: | diff --git a/internal/ui/web/js/cards.js b/internal/ui/web/js/cards.js index 141f46e..ce41bc0 100644 --- a/internal/ui/web/js/cards.js +++ b/internal/ui/web/js/cards.js @@ -143,7 +143,7 @@ function makeCard(i) { c.pmark = btn('pmark', [icon('shield'), h('span', { text: '代理' })], () => openProxy(i), { hidden: true }); c.sub = h('div', { class: 'card-sub' }); c.lmsg = h('div', { class: 'card-sub card-lmsg' }); - c.cfg = h('div', { class: 'card-cfg', title: '内存 · CPU 核数 · 帧率 · 数据盘(自动扩盘或指定大小,都按实际写入占电脑硬盘)' }); + c.cfg = h('div', { class: 'card-cfg', title: '内存 · CPU 核数 · 帧率 · 数据盘(指定大小时)· 数据盘现在实际占的电脑硬盘' }); c.pillText = h('span'); c.pill = h('span', { class: 'pill' }, c.pillText); c.adb = h('span', { class: 'adb-addr' }); @@ -192,7 +192,7 @@ function updateCard(c, inst) { const headless = inst.running && inst.window === false && v.key !== 'creating'; setText(c.sub, subtitle + (headless ? ' · 无头' : '') + (inst.diagnostics ? ' · 诊断模式' : '')); c.sub.title = headless ? '命令行开的,没有窗口,可以在这里关机' : ''; - setText(c.cfg, cfgText(inst.config)); + setText(c.cfg, cfgText(inst.config, inst.data_space)); let [pt, tone] = PILL[v.key]; // create's setup: our own job's progress, else what the process doing it (CLI, AUTO-MAS) left in the instance diff --git a/internal/ui/web/js/format.js b/internal/ui/web/js/format.js index 76f2a50..200dc2a 100644 --- a/internal/ui/web/js/format.js +++ b/internal/ui/web/js/format.js @@ -153,10 +153,12 @@ export function stopMethod(m) { return (STOP_METHOD[base] || `已关机(${base})`) + (term ? ',最后强行结束了模拟器进程' : ''); } -// 「内存 6 GB · 6 核 · 60 Hz · 盘 64 GB」, and without the disk for 自动扩盘 (the default, nothing to tell): what each -// number is, without a hover -export function cfgText(cfg) { +// 「内存 6 GB · 6 核 · 60 Hz · 盘 64 GB · 占 12.3 GB」: what each number is, without a hover. The disk size only for a +// set size (自动扩盘 is the default, nothing to tell); 占 is what the data disk takes on the computer now +// (space.host_bytes, only what was written), left out when unknown. +export function cfgText(cfg, space) { cfg = cfg || {}; const disk = cfg.data_disk_mode === 'manual' ? ` · 盘 ${cfg.data_partition_gb || '—'} GB` : ''; - return `内存 ${fmtMem(cfg.memory_mb)} · ${cfg.cpu || '—'} 核 · ${cfg.fps || '—'} Hz${disk}`; + const used = space && space.host_bytes >= 0 ? ` · 占 ${fmtBytes(space.host_bytes)}` : ''; + return `内存 ${fmtMem(cfg.memory_mb)} · ${cfg.cpu || '—'} 核 · ${cfg.fps || '—'} Hz${disk}${used}`; } diff --git a/scripts/test_card_cfg.mjs b/scripts/test_card_cfg.mjs new file mode 100644 index 0000000..88eb159 --- /dev/null +++ b/scripts/test_card_cfg.mjs @@ -0,0 +1,20 @@ +import assert from 'node:assert/strict'; +import { readFile } from 'node:fs/promises'; +import test from 'node:test'; + +const source = await readFile(new URL('../internal/ui/web/js/format.js', import.meta.url), 'utf8'); +const { cfgText } = await import(`data:text/javascript;base64,${Buffer.from(source).toString('base64')}`); + +const cfg = { memory_mb: 4096, cpu: 4, fps: 30, data_disk_mode: 'auto', data_partition_gb: 256 }; + +test('the card shows what the data disk takes on the computer', () => { + assert.equal(cfgText(cfg, { host_bytes: 12.34 * 2 ** 30 }), '内存 4 GB · 4 核 · 30 Hz · 占 12.3 GB'); + assert.equal(cfgText({ ...cfg, data_disk_mode: 'manual', data_partition_gb: 64 }, { host_bytes: 512 * 2 ** 20 }), + '内存 4 GB · 4 核 · 30 Hz · 盘 64 GB · 占 512 MB'); +}); + +test('an unknown size is left out, not shown as a dash', () => { + assert.equal(cfgText(cfg, { host_bytes: -1 }), '内存 4 GB · 4 核 · 30 Hz'); + assert.equal(cfgText(cfg, null), '内存 4 GB · 4 核 · 30 Hz'); + assert.equal(cfgText(cfg), '内存 4 GB · 4 核 · 30 Hz'); +}); From a1506ba9af335191b07aef95fbd6d516abe17b70 Mon Sep 17 00:00:00 2001 From: qiyinxi Date: Thu, 12 Nov 2026 23:03:38 +0100 Subject: [PATCH 3/3] =?UTF-8?q?ModAVDManager=20v0.9.0=20=E7=9A=84=E8=AF=B4?= =?UTF-8?q?=E6=98=8E=E5=92=8C=20SHA256SUMS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 挑进 #140(实例卡片显示数据盘实际占的电脑硬盘)。 --- release/0.9.0.SHA256SUMS.txt | 3 ++ release/0.9.0.md | 62 ++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 release/0.9.0.SHA256SUMS.txt create mode 100644 release/0.9.0.md diff --git a/release/0.9.0.SHA256SUMS.txt b/release/0.9.0.SHA256SUMS.txt new file mode 100644 index 0000000..c3fc022 --- /dev/null +++ b/release/0.9.0.SHA256SUMS.txt @@ -0,0 +1,3 @@ +5dbdd688052859a8e0b0cea5a0ac77a255ac2df9b3bd4b468fd251734f786259 ModAVD.exe +a0e10bf96063d8abab6a8502b10604cdab59743becdd8b0c29e6c5496d839b4e ModAVDManager-0.9.0-win-x64.zip +bc35ebd7d67759e2bf9bb8519d52027d6321f46758e1bc9d29c08c872c58f62c tools/modavd.exe diff --git a/release/0.9.0.md b/release/0.9.0.md new file mode 100644 index 0000000..484a578 --- /dev/null +++ b/release/0.9.0.md @@ -0,0 +1,62 @@ +# ModAVDManager v0.9.0 + +- `ModAVD.exe`:`5dbdd688052859a8e0b0cea5a0ac77a255ac2df9b3bd4b468fd251734f786259` +- `tools/modavd.exe`:`bc35ebd7d67759e2bf9bb8519d52027d6321f46758e1bc9d29c08c872c58f62c` + +随 ModAVD 0.41.0 进包。下面是相对 v0.8.0 的改动。这一版主要是:没起名的实例显示 `emu-N`,不再显示文件名 `mas_N`,卡片上能看到实例占了多少硬盘;公开版本号和模拟器构建号分开;整包更新遇到根目录文件被别的程序(比如 MAA)占着时,换包前就停,不再换到一半;问题包里能看出模拟器占了多少内存。 + +## 变更 + +- 没起名的实例显示 `emu-0`、`emu-1` 这样的名字,不再显示文件名 `mas_0`。新建和设置里名称框的占位、「不填就显示…」提示跟着改。卡片副标题照旧写编号,起了名的照旧带文件名。盘上的 `avd\mas_N.avd`、`mas_N.ini`、日志名都不变,老根目录不用搬。(ModAVDManager#135、ModAVDManager#139) +- 卡片上的规格不再写「盘自动扩」:自动扩盘是默认,不用写;指定了大小的照旧写「盘 N GB」。(ModAVDManager#139) +- 卡片上的规格末尾加上数据盘现在实际占的电脑硬盘,比如「占 12.3 GB」,只算写进去的;读不到就不写。(ModAVDManager#140) +- 电脑检查去掉「检查对象」下拉框:0.7.0 起开机前不再按实例查内存,所有实例的检查结果都一样。检查结果的标题是「暂时不能开机」,顶栏状态去掉「内存不足」。(ModAVDManager#136) +- 版本号和模拟器构建号分开:0.41 起 ModAVD 的公开版本号自己往上加,模拟器构建号(`mas-N`)只记在包里 `modavd-manifest.json` 的 `"build"`。管理器认本地版本、装包时核对模拟器都改看 `"build"`;没有 `"build"` 的老包照旧按版本中间那位核对。开机要求的最低构建号照旧按 `mas-N`。(ModAVDManager#135) +- 开机守护日志 `logs\modavd-bootwatch.log` 在开机后和之后每 10 分钟写一行模拟器的提交内存、工作集和电脑的剩余内存;问题包 `summary.txt` 里每个 qemu-system 进程多一行内存,另加一节「占内存最多的程序」(按提交排前 10 个,同名合并,只写程序名、进程数和内存,不写命令行和路径)。只在 Windows 上有。(ModAVDManager#138) + +## 修复 + +- 整包更新时,如果根目录里要换或要删的文件正被别的程序载入着(比如 MAA 载入的 `extras\modavd_extras.dll`),以前要到换完 `sdk\emulator` 以后替换它时才失败,根目录停在换了一半的状态,直到关掉那个程序才能收尾。现在换包前先逐个试一下:被占着就停,什么都没动,暂存的新版留着,提示是哪个文件、先关掉载入它的程序再装。只在 Windows 上检查。(ModAVDManager#137) + +## 给调用方(AUTO-MAS) + +- `protocol` 还是 2:没有删命令、参数和 `--json` 字段,没有新的错误码和退出码。调用方不用改。 +- `modavd list` 的人读表格:没起名的实例,名称列写 `emu-N`(以前写文件名 `mas_N`)。`--json` 的 `name`(`mas_N`)、`title` 不变。(ModAVDManager#135、ModAVDManager#139) +- `update install` 遇到根目录文件被占用时是 `busy`(退出码 5),消息「<文件> 正被别的程序占用(多半是 MAA 之类载入了它),什么都没动。请先关掉它再装」;状态退回「待安装」,关掉那个程序后再 `install` 就行。(ModAVDManager#137) +- 管理器自己的接口 `GET /api/check` 去掉了 `index` 参数和返回里的 `instance_index`、`memory_mb`、`root_ready`;`ready` 为 `false` 就是所有实例都开不了机。命令行 `check --memory` 和 MCP `check_host` 的 `memory_mb` 照旧接受、不起作用。(ModAVDManager#136) + +## 下载与核对 + +用 Go 1.26.5、`GOTOOLCHAIN=local` 运行仓库里的 `build.ps1`,能编出相同的字节。单独下载的包里还有 Go 的许可原文和文件清单。请用附件 `SHA256SUMS.txt` 核对 zip 和解压出的两个 exe,例如在 PowerShell 里运行 `Get-FileHash .\ModAVDManager-0.9.0-win-x64.zip -Algorithm SHA256`。 + +单独下载的管理器不会自己更新,新版本要手动替换;ModAVD 包里的那份随 ModAVD 整包一起更新。单独使用时请给 `--root` 或设置 `MODAVD_ROOT`,否则会提示找不到 ModAVD 根目录。不要把单独下载的 zip 解压到 ModAVD 根目录,覆盖整包里的文件。 + +## English + +Shipped in ModAVD 0.41.0. Changes since v0.8.0. This release mostly brings: instances without a name of their own show as `emu-N` instead of the file name `mas_N`, and the card shows how much disk each instance takes; the public version number is separate from the emulator build number; a whole-package update stops before swapping anything when another program (such as MAA) holds a root file, instead of stopping halfway; and problem reports show how much memory the emulator takes. + +### Changes + +- Instances without a name of their own show as `emu-0`, `emu-1` and so on instead of the file name `mas_0`. The placeholder and the hint of the name box in the create dialog and the settings follow. The card subtitle still shows the index, and named instances still show the file name. `avd\mas_N.avd`, `mas_N.ini` and the log names on disk do not change, so old roots need no moving. (ModAVDManager#135, ModAVDManager#139) +- The card no longer says "盘自动扩" (disk grows by itself): it is the default and needs no mention; a set size still shows as "盘 N GB". (ModAVDManager#139) +- The card ends with what the data disk takes on the computer's disk now, such as "占 12.3 GB" (takes 12.3 GB), counting only what was written; left out when it cannot be read. (ModAVDManager#140) +- The host check drops its "检查对象" (checked for) drop-down: since 0.7.0 nothing is checked per instance before a start, so every instance gets the same result. The result title is "暂时不能开机" (cannot start yet), and the top bar no longer has an "out of memory" state. (ModAVDManager#136) +- The version number is separate from the emulator build number: from 0.41 ModAVD's public version goes up on its own, and the emulator build (`mas-N`) is recorded only as `"build"` in the package's `modavd-manifest.json`. The manager reads `"build"` to tell the local version and to check the emulator when installing a package; old packages without `"build"` are checked against the middle number of the version as before. The minimum build needed to start is still in `mas-N`. (ModAVDManager#135) +- The boot watcher log `logs\modavd-bootwatch.log` gets a line after boot and every 10 minutes with the emulator's commit and working set and the computer's free memory; the problem report's `summary.txt` gets a memory line for each qemu-system process and a section with the 10 programs that commit the most memory (same names merged; only program names, process counts and memory, no command lines or paths). Windows only. (ModAVDManager#138) + +### Fixes + +- When a root file to be replaced or deleted was loaded by another program during a whole-package update (for example `extras\modavd_extras.dll` loaded by MAA), the update used to fail only when replacing it after `sdk\emulator` had been swapped, leaving the root half swapped until that program was closed. Now each file is tried before the swap: if one is held, the update stops with nothing changed, keeps the staged package, and says which file it is and to close the program that loaded it first. Windows only. (ModAVDManager#137) + +### For callers (AUTO-MAS) + +- `protocol` is still 2: no command, option or `--json` field was removed, and there are no new error codes or exit codes. Callers need no change. +- The human-readable table of `modavd list` shows `emu-N` in the name column for instances without a name of their own (the file name `mas_N` before). `name` (`mas_N`) and `title` in `--json` do not change. (ModAVDManager#135, ModAVDManager#139) +- `update install` returns `busy` (exit code 5) when a root file is held by another program, with the message " 正被别的程序占用(多半是 MAA 之类载入了它),什么都没动。请先关掉它再装" (the file is in use by another program, probably something like MAA that loaded it; nothing was changed; close it first); the state goes back to staged, and `install` works again once that program is closed. (ModAVDManager#137) +- The manager's own `GET /api/check` drops the `index` parameter and `instance_index`, `memory_mb` and `root_ready` from its result; `ready` being `false` means no instance can start. `check --memory` on the command line and `memory_mb` of MCP `check_host` are still accepted and have no effect. (ModAVDManager#136) + +### Download and verification + +Running the repository's `build.ps1` with Go 1.26.5 and `GOTOOLCHAIN=local` builds the same bytes. The standalone package also carries Go's license text and the file list. Check the zip and the two extracted exe files with the attached `SHA256SUMS.txt`, for example `Get-FileHash .\ModAVDManager-0.9.0-win-x64.zip -Algorithm SHA256` in PowerShell. + +The standalone manager does not update itself; replace it by hand for a new version. The copy in the ModAVD package is updated with the whole ModAVD package. When using it standalone, pass `--root` or set `MODAVD_ROOT`, or it reports that it cannot find the ModAVD root. Do not extract the standalone zip into a ModAVD root over the package's files.