# 小貓中文 — 接手說明 (HANDOFF) 目標:DOS 常駐 (TSR) Big5 中文顯示 + 注音輸入,跑在 js-dos 6.22(瀏覽器/手機),部署為 HF static Space。 傳統記憶體越少越好(現況常駐約 16 KB,不強制 600K)。授權 GPL-3.0-only + GPLv3 §7(b) 附加條款(保留作者 HelloSun,見 LICENSE)。全部元件開源,不含專有軟體。 ## 作者聲明規則(修改時務必遵守) - 作者 **HelloSun**、首版 **v1.0 / 2026-10-25**、版權 **Copyright (C) 2026 HelloSun** 出現在:每個原始檔檔頭、`LICENSE`、`NOTICE.md`、`README.md`、`index.html` 頁尾、 以及 `src/xiaomao.c` 的 `report()`(`M6`,程式每次載入都會顯示)。**不得移除**(GPLv3 §7(b));加入自己的修改請另加自己的名字並註明為修改版。 - 作者資訊由 `apply_notice.py` 的三個常數產生過;改版本或日期時,請連同上述所有位置一起更新。 ## 一鍵流程 `HF_TOKEN=... HF_SPACE=user/space ./build.sh`(兩者是腳本開頭變數,token 不入檔)。空目錄也能跑:自動建 Python venv、下載並以雜湊驗證 Open Watcom 1.9、JWasm+HimemX 原始碼(現場編成 HIMEMX.EXE)、GNU Unifont、FreeDOS 1.4 Floppy、js-dos 6.22.60(npm),再產生字型/詞庫、編譯、組開機片、產生 `dist/`、上傳。 主機需求:bash gcc make nasm mtools unzip curl gzip python3(venv)。快取在 `.cache/`,工具在 `.build/`(皆 .gitignore)。 ## 現況(已驗證) - FreeDOS 開機 → `FDCONFIG.SYS` 載 HIMEMX → `FDAUTO.BAT` 載 XIAOMAO.EXE → 回到 `A:\>`;顯示 MEM;`Ctrl+Space` 注音;候選列在最底列;Backspace 刪整個中文字。 - 手機尺寸(390x844)+觸控虛擬鍵盤驗證過;DOSBox 核心與開機片都自架,不依賴外部 CDN。 ## 架構(傳統「中文系統」作法:文字影子 + 繪圖顯示) - `src/xiaomao.c`:TSR。`video_service`(INT10 文字模式 BIOS 模擬)、`refresh`(渲染器)、`key_service`(INT16 + 注音)、載入器 `main`。 - `src/xms.asm` (NASM OMF):XMS 包裝、INT10/16/2F 掛勾(私有 2 KB 堆疊在 _TEXT,SS=CS;INT10 掛勾把暫存器框架以遠指標交給 C)、`bios10_call`、`get_rom_font`(INT10 AX=1130h)、`cpu_idle`。 helper 只能改 AX;Watcom 暫存器呼叫 AX,DX,BX,CX(第二參數在 DX);large model 用 `retf`;符號後綴 `_`。 - 顯示:BIOS 模式 12h(640x480x16),CRTC 垂直顯示結束改 399(只顯示 400 線=25 列x16)。程式眼中仍是模式 3:BDA(0040:xx)被改寫成模式 3/80 欄/25 列。 影子文字在 `B800:0000`;畫面像素在平面偏移 0000-7CFF,經 A000 視窗寫入。渲染器每 tick(INT16 輪詢、阻塞前強制)逐列比對影子與「已繪副本」(`B800:6000` 字元/屬性、`B800:7000` 種類),只重畫變動的格子。 Big5 偵測:前導 A1-F9 + 後隨 40-7E/A1-FE(`Ctrl+\` 可關);漢字 16x16 由 XMS 取(64 項快取),ASCII 用 ROM 字型。游標以底線疊畫,BDA/CRTC 游標暫存器皆會同步。 - **DOSBox 的 VGA 陷阱(都已實測,別再踩)**: 1. 模式 12h 下 `B800` 不是 RAM;GC 雜項暫存器(GC6) map=3(B8000) 會讓 DOSBox 變成 CGA 模式。 2. 解法:GC6=0x01(A0000 起 128KB 視窗)。此時 `B800:0000` 對應平面偏移 0x8000(寫入 map mask=0Fh、讀 plane 0,行為如 RAM),與 A000 低 32 KB 的畫面互不重疊,且完全不需切換視窗。 3. 寫模式 2 的背景填色在 DOSBox 無效;改用寫模式 0 + Set/Reset(GC0=色、GC1=0F、GC8=位元遮罩)。 4. 部分遮罩寫入前必須「真的讀一次」同位址以載入 latch(用 volatile sink 變數,否則編譯器會丟掉讀取,未遮罩位元會帶入垃圾)。 5. 畫完一列必須還原 GC1=0、GC8=FF、GC0=0,否則程式之後寫 B800 會被 Set/Reset 污染。 - 輸入:INT16 AH=0/1/0x10/0x11 掛勾 → IME 狀態機 → Big5 兩位元組入 16 字佇列。BS 加倍(一次退兩格)只在 DOS 內部讀鍵時(InDOS≠0)啟用,直接呼叫 INT16 的程式(PE2/XEDIT)收到單一 BS。 - 資料:`FONT.DAT`("ETNF" 18 byte 頭, ASCII 256x16, CJK 32 byte/字, 索引 (lead-0xA1)*157+trail索引) 與 `IME.DAT`("ETNI", 12 byte 頭, 5 byte 記錄 key/offset/count),載入 XMS。 key=(((ini*4+med)*14+fin)*5+tone);XMS 搬移長度必須為偶數;XMS 只在安全點(INT16/INT10 內)呼叫,不在計時器 ISR。 - 常駐大小:build.sh 兩階段編譯,由連結 map 的 STACK 段位址 +0x10 得 `TSR_PARAS`;init 用大緩衝(含 4000 B 舊畫面)放堆疊(`-k10240`,不常駐)。 - 防重複載入 INT2F AX=D7A0h→584Dh;再次執行 XIAOMAO 只顯示 MEM。 - 附加軟體:`src/addons/xedit.c`(PE2 風格直接寫 B800 的編輯器,用來驗證直接寫顯示記憶體相容性)。 - 網頁:`index.html`(含「示範 Demo」:`runDemo()` 以 `controller.simulateKeyEvent` 送鍵,`step(字幕, 閱讀停留ms, 動作)`;`SPEED=4` 倍速:按鍵間隔約 160 ms(下限 50 ms,DOS 需要)、字幕停留約 0.6–1.6 s,全程約 40 秒)。HF 對二進位檔回 302 無 CORS,所以 `emu.b64.js`(wdosbox.js+wasm 的 base64) 與 `dos.b64.js`(開機片 zip 的 base64) 以 Blob URL 供 js-dos; monkeypatch `XMLHttpRequest.prototype.open` 把 `wdosbox.js`/`wdosbox.wasm.js` 對應到 Blob URL(js-dos 以 `.js`→`.wasm.js` 推導 wasm 檔名)。 - FreeDOS 開機片:取 FD14 `144m/x86BOOT.img`,刪除安裝用檔,換 `dos/FDCONFIG.SYS`、`dos/FDAUTO.BAT`(CRLF 由 build.sh 轉)。FreeDOS 主控台輸出經 INT 10h TTY(已驗證)。 ## 編譯注意 Open Watcom 1.9:`wcl -bt=dos -ml -0 -os -s -zu -k6144`(`-s` 必要:私有堆疊上不可堆疊檢查)。無 `_AX` 偽暫存器;`_psp` 需自行 `extern unsigned _psp;`。 ## 測試方式 無本機 DOS 模擬器:`python3 tests/smoke.py --dist dist --chromium `(Playwright,截圖到 /tmp/xm-shots,只做粗略像素斷言;請人工看截圖)。 自己寫測試 EXE 時:用 build 裡的 Open Watcom 編譯,放進映像(參考 build.sh 的組映像段),改 `dos/FDAUTO.BAT` 即可。 Chromium 旗標:`--no-sandbox --disable-gpu --disable-dev-shm-usage`。截圖檔寫入有延遲,讀檔前稍等。 ## 已知限制 / 待辦 1. 不支援程式直接改 CRTC/VGA 暫存器做文字特效(游標暫存器除外)、載入文字模式字型、閃爍屬性。 2. 渲染為 tick 驅動(約 18 fps);可考慮在 INT10 寫入後立即小範圍重畫,或重新程式化 PIT 提高更新率。 3. 輸入法只有注音(候選字已可分頁,每音最多 63 個);無詞組/聯想;可加倚天/倉頡/大易。 4. Big5 與 CP437 畫框字元衝突只能用 `Ctrl+\` 手動切換;可加自動偵測。 5. 可加 JEMM386/UMB 讓 TSR 載入高記憶體(現約 15 KB 傳統記憶體)。 6. 自動化測試只有 smoke test;可加截圖比對基準。