AI x SFC Player

Posts · · 繁體中文 · 简体中文 · 日本語

Our Gomoku in HD, ROM untouched: an AI makes the HD pack itself

In the previous post an AI made Bianhe, a 2.5D Gomoku, from one sentence. The Super Famicom screen is 256×224: the 900-year-old scroll is squeezed into 104 pixels of height, and the captions use a 12-pixel bitmap font.

The player now supports HD packs. The ROM is not changed by a single byte; tiles and text that the player recognises on screen are drawn from the pack’s high-resolution pictures instead. This time we wanted to know: given only the game’s ROM, can the AI make the pack itself?

The original screen
The original screen (256×224, shown at 2×).
The same screen with the HD pack
With the HD pack (4×, 1024×896): the scroll has the painting's own detail, the text is Noto Serif TC.
30 seconds: HD off for 5 s, on for 10 s, twice (straight from the player's emulator, with the game's music). This is what pressing H does.

Three steps

1. Make an empty folder, put your ROM in it and install the skills:

mkdir bianhe-hd && cd bianhe-hd
cp ~/games/bianhe.sfc .
npx https://aixsfc.app/skill/aixsfc.tgz

The installer adds three Claude Code skills (sfc-hd is the one that makes HD packs) and the MCP tools: an emulator, memory reading and writing, screenshots.

2. Start claude and say one paragraph (we wrote it in Chinese; this is a translation):

prompt>

bianhe.sfc is a Gomoku game I made myself. Please use sfc-hd to make me an HD pack: resample the scrolling Qingming scroll at the top from the high-resolution original on Wikimedia Commons (public domain); redraw the Chinese text on screen with an open-licence font (e.g. Noto Serif TC). Don't ask me anything along the way; you choose the scale. Zip it when done and write a report of the process.

We added nothing after that. Normally sfc-hd first asks how to enhance the pictures (an AI upscaler on your computer, an AI redraw, your own art) and which font to use for the text. We answered all of that up front, so it never stopped.

3. Play: 14 minutes later it handed back bianhe-hd-pack.zip (7.8 MB). Open aixsfc.app/player, load the game, and choose HD → Load HD pack (.zip)… in the toolbar. That is the right-hand screen above.

What it did

Understanding the screen first

It ran the game in the emulator, saved a state, and read video memory, palettes and PPU registers out of it. Three findings:

A pack’s text recognition only finds characters on a background layer, aligned to the 8×8 grid, so it decided to replace each character as ordinary tiles instead. The result is the same, and it worked that out on its own.

The scroll: from the ROM to the museum scan

  1. Find the whole scroll in the ROM. The tiles start at $40000, 13 per column, 263 columns: 2104×104 pixels. It checked the extracted picture against the 429 tiles on screen: all 429 identical.
  2. Download the original. The full scan on Wikimedia Commons is a 38414×1800-pixel, 19 MB JPEG.
  3. Line them up. The game’s scroll is the original cropped, shrunk and recoloured, so first it had to find how one maps onto the other. A correlation search at low resolution, then fine tuning, gave one linear map: game x → original X = 1913 + 16.94x. Searching each 64-pixel stretch on its own gave an offset of 0 everywhere, so one map fits the whole scroll.
  4. Resample. Each HD pixel is the average of the roughly 4.2×4.2 original pixels it covers: an 8416×416 scroll.
  5. Match the colours. The scan has the museum’s cool grey; the game has a warmer silk tone. A least-squares colour transform keeps the HD scroll in the game’s colours, so pressing H doesn’t make the colours jump.
  6. Cut into tiles. 3419 tiles. Each key is a hash of the original tile’s pixels plus its palette, pointing at the 32×32 block in the same place on the HD scroll.
Part of the scroll: the original pixels above, HD below
The same stretch of the scroll: the game's own pixels (4×) above, the HD pack below. The people on the boats, the eaves and the ropes are all visible now.

The text: a serif font

Text close-up: the original bitmap font on the left, HD on the right
Left: the original 12-pixel bitmap font (4×). Right: Noto Serif TC.

Working within limited permissions

This Claude Code session was allowed to read and write files, use the web, and run node, python3 and curl, nothing else. To decode the JPEG it first reached for macOS sips or npm install, but both needed the user’s approval, and the instructions said not to ask.

So it downloaded the jpeg-js package from the npm registry with curl, checked it against the SHA-1 the registry publishes, and unpacked it with a small program of its own. The font renderer was written for the same reason.

Playing with the pack

The HD screen with the scroll at the riverside boats
The scroll has reached the boats by the river. The board below is Mode 7, which packs don't cover, so it keeps its pixels.

A bug we found while playing

The first time we applied the pack in the player, the board in the lower half was covered in vertical stripes. The cause was in the player: this game switches from Mode 1 to Mode 7 halfway down the same frame, and the Mode 7 scanlines didn’t clear the “which tile drew this pixel” record left by the scanline above, so the board was replaced with tiles from the scroll.

The fix was one line, with a test, and the player no longer does this. That alone made the demo worthwhile: it took a game that really switches modes mid-screen to run into it.

Not done yet

Numbers

Instructions to the AI1 paragraph (4 sentences)
Total timeabout 14 minutes
Tool calls104 (Claude Opus 5.5, 94 replies)
AI output tokens69,082
Total tokens processedabout 8 million (mostly cache reads)
Estimated costabout US$4 (at Anthropic API list prices, November 2026; subscriptions are billed differently)
The pack4×, 3543 tiles (3419 scroll, 124 text), 7.8 MB zipped

What’s in a pack

A pack is a folder (or a zip) with one manifest.json and a few PNGs. The manifest only lists which hash goes with which block of which picture, so:

This pack’s scroll comes from a public-domain painting, the font is SIL OFL, and the game is our own, so it can be shared. A pack made from a commercial game is a derivative of that game: keep it for your own use, and never share a zip that holds a ROM together with its pack.

To try it yourself, run npx https://aixsfc.app/skill/aixsfc.tgz in an empty folder and start claude; see the home page.

Sources and licences