READMESource: main@ef19d4fe
dsh-doom · DOOM (Shareware) in your DSH Web UI
在 DeepSeek Harness Web UI 里玩 DOOM 共享版(Shareware):一个可拖动的浮动游戏窗口,真实第一人称 3D(640×400)+ 枪械音效 + 关卡音乐,纯键盘操作。
安装方式与皮肤插件(如 dsh-liang-skin)相同:静态注册进 DSH profile,重启 DSH 后依然生效,无需 cordis_define、无需审批。
██████╗ ██████╗ ██████╗ ███╗ ███╗
██╔══██╗██╔═══██╗██╔═══██╗████╗ ████║
██║ ██║██║ ██║██║ ██║██╔████╔██║
██║ ██║██║ ██║██║ ██║██║╚██╔╝██║
██████╔╝╚██████╔╝╚██████╔╝██║ ╚═╝ ██║
╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝
· SHAREWARE · 第一幕 9 关 + 隐藏关 · 完整武器/怪物 ·
安装
需要已安装 DeepSeek Harness CLI。安装本身可以在 DSH 运行时执行(只改磁盘配置),重启后生效。任选其一:
方式一:GitHub(推荐)
dsh plugin --profile web add 'github:Banboosu/dsh-doom'
dsh plugin 会从 GitHub 拉取仓库、注册进 profile 的 dsh.profile.bundles(见 ~/.dsh/profiles/web/package.json)并安装。
方式二:本地路径(开发迭代)
git clone https://github.com/Banboosu/dsh-doom.git
cd dsh-doom
dsh plugin --profile web add .
以链接方式安装:改代码后无需重新安装,重启 DSH 即生效。
验证
dsh --profile web --dump-config | grep -B1 -A2 dsh-doom # 应出现 - id: dsh-doom 配置层
然后重启 DSH。重启后插件自动加载并常驻,之后每次重启都在。
使用
- 在对话输入框输入
/doom(或/查看命令列表)即可打开/关闭游戏窗口——每执行一次切换一次。窗口开关状态由 Host 端持有、浏览器轮询同步,因此在新会话、历史会话乃至 Web UI 首页都有效。 - 点击弹出游戏窗口(可拖动,标题栏拖拽,右上角关闭)。
- 下载引擎资产(约 4.6 MB,仅首次)后显示标题画面。
- 点击画面:捕获键盘 + 解锁声音(浏览器自动播放策略要求一次用户手势)。再次点击标题栏可释放键盘。
- 进入关卡即播放该关音乐(GeneralUser GS 音源预渲染的 OGG)。窗口状态栏有 🔊 音量滑条(记住设置)。
| 操作 | 按键 |
|---|---|
| 移动 / 转向 | 方向键 或 WASD |
| 使用 / 开门 | 空格 |
| 开火 | F 或 Ctrl |
| 加速跑 | Shift |
| 换武器 | 1–7 |
| 自动地图 | Tab |
| 菜单 | Esc(菜单内 F10 退出,或点窗口 ✕) |
| 暂停 | P |
| 快速存档 / 读档 | F6 / F9 |
仓库结构
dsh-doom/
├── package.json # 静态插件包(dsh.client 声明 web client bundle)
├── cordis.patch.yml # 把 dsh-doom 行插入 Host 组合
├── src/
│ ├── index.js # Host 半侧:/dsh-doom/assets/* 路由 + /doom 命令 + 窗口状态端点
│ ├── doom-engine.js # 引擎胶水(单一事实源):WASM 直连实例化 + MEMFS + WebAudio
│ └── client/index.js # 浏览器半侧:游戏窗口 + /doom 命令行 + 状态轮询(React.createElement)
├── lib/client.js # 构建产物(__ModuleLoader__ bundle,已提交,安装无需构建)
├── doom/
│ ├── doomgeneric_pi.c # pi-doom 的平台 shim(帧缓冲/输入/键码)
│ └── doomgeneric_dg_sound.c # dsh-doom 的 WebAudio 声音模块(C 侧)
├── scripts/
│ ├── build-client.mjs # esbuild → lib/client.js
│ ├── rebuild-doom.sh # 用 emcc 从 doomgeneric 源码重建 assets/doom.wasm
│ ├── render-music.sh # MUS → OGG(mus2mid + fluidsynth + GeneralUser GS)
│ └── patch-doom-wipe.py # 溶解过场修复(一帧一帧推进,浏览器里可见)
├── assets/
│ ├── doom.wasm # doomgeneric WASM(本仓库构建,含声音模块)
│ ├── doom1.wad # DOOM 共享版 v1.9(id Software 免费软件,可再分发)
│ └── music/*.ogg # 每关预渲染音乐(64 kbps Vorbis,共 ~14 MB)
├── plugin/ # 【旧】动态插件形态(cordis_define 时代遗留,仅供参考)
├── demo/ # 独立演示页(不依赖 DSH)
└── AGENTS.md # 给 AI agent 的仓库导读
技术要点
- WASM 直连实例化,不用 emscripten 胶水:pi-doom 的
doom.js以-s ENVIRONMENT=node编译(ENVIRONMENT_IS_NODE=true写死,浏览器必崩)。doom.wasm的导入只有 19 个标准 emscripten 函数,src/doom-engine.js逐一实现(libc syscall + wasi fd_* + 微型 MEMFS),因此免 eval、免 import、CSP 安全。 - 自研声音模块:
doomgeneric_dg_sound.c把 SFX 事件转发给 4 个 WebAssembly 导入(DG_SoundStart/Stop/IsPlaying/UpdateParams),JS 侧用 WebAudio 解码播放 WAD 里的 DMX 音效;音乐则解析 MUS(已与 chocolate-doom mus2mid 逐音符核对)并在 JS 侧调度合成,优先播放预渲染 OGG。 - 溶解过场修复:原版 D_Display 的 wipe 忙等循环在浏览器里一帧画完、不可见;
patch-doom-wipe.py改为每调用推进一帧,渲染循环(~60fps)能完整显示约 40 帧的招牌熔解动画(~0.7s)。 - Host 状态 + 浏览器轮询:窗口开关状态由 Host 端
/doom命令持有,浏览器每 500ms 轮询/dsh-doom/state镜像(静态插件无 harness RPC,用普通 HTTP 端点替代)——任何会话、任何页面位置都能正确开关。
校验
sha256sum assets/doom.wasm
# 4c33ef4b42c9f046db02b1c94ce624205f2c6de8bf77e37ed94f5481054300c9 assets/doom.wasm
# (含声音模块 + 溶解过场修复,可用 scripts/rebuild-doom.sh 复现)
sha256sum assets/doom1.wad
# 1d7d43be501e67d927e415e0b8f3e29c3bf33075e859721816f652a526cac771 assets/doom1.wad
致谢 / 许可
- doomgeneric(GPL-2.0)— DOOM 引擎可移植化实现;WASM 构建基于 pi-doom(GPL-2.0)的构建脚本与平台 shim
- DOOM 共享版 WAD(v1.9)— id Software 官方免费分发
- 音乐渲染音源 — GeneralUser GS v1.471(Shunsuke Kato,自由音源)
- 安装方式参考 dsh-liang-skin
No comments yet. Be the first to write one.