不改 ROM,讓《汴河煙雨》變成 HD:AI 自己做出高畫質素材包
上一篇裡,AI 用一句話做出了 2.5D 五子棋《汴河煙雨》。超任的畫面只有 256×224,清明上河圖被縮成 104 像素高,題簽用的是 12 像素的點陣字。
播放器現在支援 HD 素材包:ROM 一個位元組都不改,畫面上認得的圖塊和文字,改用素材包裡的高解析度圖片來畫。這次我們想知道:只給 AI 這個遊戲的 ROM,它能不能自己把素材包做出來?


三個步驟
1. 建一個空資料夾,放進自己的 ROM,安裝 skill:
mkdir bianhe-hd && cd bianhe-hd
cp ~/games/bianhe.sfc .
npx https://aixsfc.app/skill/aixsfc.tgz
安裝程式會放好三個 Claude Code skill(其中 sfc-hd 負責做 HD 素材包)和 MCP 工具(模擬器、讀寫記憶體、截圖)。
2. 開 claude,說一段話:
bianhe.sfc 是我自己做的五子棋遊戲(煙雨汴河)。請用 sfc-hd 幫我做一個 HD 素材包: 上方捲動的清明上河圖,改用 Wikimedia Commons 上的高解析度原圖(公有領域)重新取樣; 畫面上的中文字,用開源授權的字型(例如 Noto Serif TC)重新繪製。 過程中不用問我,倍率你決定。完成後打包成 zip,並記錄製作過程報告。
之後沒有再補充任何說明。平常 sfc-hd 會先問你:圖要怎麼放大(本機 AI 放大、AI 重繪、自己畫)、字要用哪個字型。這裡我們一次說完,所以它全程沒有停下來。
3. 播放: 14 分鐘後它交回 bianhe-hd-pack.zip(7.8 MB)。打開 aixsfc.app/player,載入遊戲,從工具列的 HD 選單選「載入 HD 素材包(.zip)…」,就是上面右邊的畫面。
它做了什麼
先看懂畫面
它在模擬器裡跑遊戲、存檔,從存檔讀出顯示記憶體、調色盤和 PPU 暫存器,得出三件事:
- 畫面在第 105 條掃描線切開:上半部是一般背景(Mode 1),下半部是透視棋盤(Mode 7)。
- 長卷是背景層,用一個 64 欄的環形區域一欄一欄串流進顯示記憶體。
- 題簽和「你的回合」這些字不是背景文字,而是 16×16 的精靈。
素材包的「文字辨識」只認得背景層上對齊 8×8 格線的字,所以它決定把每個字當成普通圖塊來替換。效果一樣,而且它自己判斷出了這點。
長卷:從 ROM 找到原圖,再對上博物館掃描檔
- 在 ROM 裡找到整條長卷。 圖塊從
$40000開始,一欄 13 塊,共 263 欄,就是 2104×104 像素。它把抽出來的圖和畫面上的 429 個圖塊逐一比對,429 個全部相同。 - 下載原圖。 Wikimedia Commons 上的全卷掃描檔是 38414×1800 像素、19 MB 的 JPEG。
- 對位。 遊戲的長卷是原圖裁切、縮小、調色後的版本,所以要先找出兩者的對應關係。它先在低解析度下用相關係數搜尋,再細調,得到「遊戲 x → 原圖 X = 1913 + 16.94x」這樣一個線性對應。再把長卷每 64 像素切一段各自搜尋,每段的偏移都是 0,所以整條用同一個對應就行。
- 重新取樣。 每一個 HD 像素,取原圖上對應的約 4.2×4.2 像素做平均,得到 8416×416 的長卷。
- 調色。 原圖是博物館的冷灰色調,遊戲是偏暖的絹色。它用最小平方法算出一組色彩轉換,讓 HD 長卷維持遊戲的色調,按 H 開關時不會突然變色。
- 切成圖塊。 3419 個圖塊,每塊的 key 是「原圖塊的點陣+調色盤」的雜湊值,對應 HD 長卷上同一位置的 32×32 方塊。

文字:換成宋體
- 它從 Google Fonts 只下載遊戲用到的 29 個字(Noto Serif TC,SIL OFL 授權),再加上紅色印章字「勝」「和」。
- 這台電腦上沒有現成的字型繪製工具,它就自己寫了一個 TrueType 解析器和反鋸齒填色程式。
- 每個字用原本點陣字的墨色範圍來對齊,在 0.86–1.06 倍的縮放和 ±1 像素的位移裡,找重疊最多的組合。
- 它試了 500、600、700、900 四種字重,選了筆畫粗細最接近原作的 600。
- 面板的邊框和底色保留原本的像素,只把字換掉。總共 124 個精靈圖塊。

權限受限時的變通
這次的 Claude Code 只開放讀寫檔案、上網,以及執行 node、python3、curl 這幾個指令。解 JPEG 原本想用 macOS 的 sips 或 npm install,但兩者都要使用者確認,而指示裡說了「不用問我」。
所以它直接從 npm registry 用 curl 下載 jpeg-js 的套件檔,先核對官方公布的 SHA-1,再用自己寫的小程式解開。字型的繪製程式也是因為同樣的限制才自己寫的。
在播放器裡播放
- 工具列的 HD 選單有五個選項:關、開、載入資料夾、載入 .zip、移除。手機上選資料夾不方便,用 .zip 最簡單。
- 素材包載入一次後,會以「這個 ROM」為單位存在瀏覽器裡。下次開同一款遊戲會自動套用,開關狀態也會記住。
- 鍵盤按 H 隨時開關,方便對照前後差異。
- 長卷捲動時,新露出的每一欄都會換成 HD。素材包比對的是「畫面上的圖塊」,不是 ROM 位址,所以串流進來的圖塊照樣認得出來。

我們在試玩時發現的問題
第一次在播放器裡套用時,下半部的棋盤出現了一條條直紋。原因在播放器:這款遊戲在同一格畫面裡從 Mode 1 切換到 Mode 7,Mode 7 的掃描線沒有清掉上一條掃描線留下的「這個像素來自哪個圖塊」記錄,結果棋盤被當成長卷的圖塊替換了。
修正只有一行,也加了測試,現在的播放器已經沒有這個問題。這也是做這次示範的收穫:拿一款真的會在畫面中途切換模式的遊戲來試,才會遇到這種情況。
還沒做到的
- 最右邊約 64 像素: 這一段和 Commons 的掃描檔對不太上。AI 在報告裡推測,原作可能用了別的掃描版本,或者在接縫處做過處理。對照上一篇的製作過程,比較可能的原因是:做遊戲時為了讓捲動無限循環,長卷的頭尾做了交叉淡化,這一段混進了開頭的畫面。HD 版在這段仍然接得上,只是細節和原本的像素不完全相同。
- 棋盤、棋子、雨絲、游標維持原本的像素:棋盤是 Mode 7,素材包格式不支援;其他精靈不在這次的範圍內。
數字
| 給 AI 的指示 | 1 段話(4 句) |
| 總時間 | 約 14 分鐘 |
| 工具呼叫 | 104 次(Claude Opus 5.5,94 則回覆) |
| AI 輸出 token | 69,082 |
| 處理的 token 總數 | 約 800 萬(大部分是快取讀取) |
| 估計費用 | 約 4 美元(以 2026 年 11 月的 Anthropic API 牌價換算;訂閱方案計費方式不同) |
| 素材包 | 倍率 4,3543 個圖塊(長卷 3419、文字 124),zip 7.8 MB |
素材包裡有什麼
素材包是一個資料夾(或 zip),裡面有一個 manifest.json 和幾張 PNG。manifest.json 只列出「哪個雜湊值對應圖片上的哪一塊」,所以:
- 素材包裡沒有 ROM 的任何內容,原本的點陣只以雜湊值的形式出現。
- 播放器不會執行素材包裡的任何程式,素材包只有資料。
- 比對的是畫面上的圖塊,播放器不需要知道是哪一款遊戲。
這個素材包的長卷來自公有領域的畫作,字型是 SIL OFL 授權,遊戲也是我們自己的,所以可以分享。拿市售遊戲做的素材包,屬於原作的衍生作品,請只留給自己使用;也不要把 ROM 和素材包放在同一個 zip 裡散布。
想自己試試,在空資料夾執行 npx https://aixsfc.app/skill/aixsfc.tgz 再開 claude,說明在首頁。
來源與授權
- 畫作:張擇端《清明上河圖》,12 世紀,公有領域;掃描檔:Wikimedia Commons,
File:Alongtheriver QingMing.jpg。 - 字型:Noto Serif TC,Google/Adobe,SIL Open Font License 1.1。
- 遊戲《汴河煙雨》:見上一篇。本作與任天堂無關,亦未獲其背書。