Kirby Super Star Recomp
Kirby Super Star Recomp is a native PC port of Kirby Super Star for the Super Nintendo Entertainment System with support for ScaleFX and NNEDI3 upscalers.
- Type: PC port
- Game: Kirby Super Star
- Runs on Windows
- By mpolizel
- Latest release v0.1.0, 2026-11-04
- Source: https://github.com/mpolizel/KSSSNESRecomp
README
Kirby Super Star Recomp
A native recompilation of Kirby Super Star (USA), built on snesrecomp.
Kirby Super Star is HAL Laboratory's 1996 Kirby collection for the Super NES: Spring Breeze, Dyna Blade, Gourmet Race, The Great Cave Offensive, Revenge of Meta Knight, Milky Way Wishes and The Arena, with copy abilities, helpers a second player can control, and the cartridge's SA-1 chip doing the heavy lifting.
You must legally own a copy of the game. No ROM data is distributed with this project, in the repository or in any release. The recompiled C is generated locally from your own copy and is never committed.
☕ Keep the ports coming
This project is free and always will be. Every port in this series, Kirby Super Star included, is built with many hours of AI-assisted reverse engineering, and that AI time is paid. If you enjoy playing it, a coffee at buymeacoffee.com/mpolizel keeps the AI running so more SNES games can be ported to native Recomp. Any amount helps, and thank you!
Download (ready-to-run Windows build)
Get the latest kirbysuperstar-<version>-windows-x64.zip from the
Releases page.
The zip is a setup pack: it contains the launcher, the recompiler and this source tree (with the framework patches already applied), but no game data. On first run:
- Unzip anywhere and start
KirbySuperStarSNESRecomp.exe. - Let it download the portable build tools (one time per machine), or point
it at a
cmake-clang-v1zip you already have. - Pick your own
Kirby Super Star (USA).sfc(CRC3289d0f7dc; the file name does not matter, the contents are checked). - Press Generate & rebuild. The playable game is built into
build/and started; run it from there afterwards.
In the launcher, Settings → Shader lists the scanline, CRT and upscaler
presets; choosing one switches the renderer to OpenGL automatically. A fresh
install starts with no shader (the plain picture), the lightest option for
any graphics card; pick a CRT or upscaler preset there if yours has room.
Your choice is saved in config.ini and kept. The upscalers include
ScaleFX and the neural NNEDI3 presets.
During play, Ctrl+L (or Select+L3 on a controller) reopens the
launcher: shader, window scale, volume and controls apply when you press
Resume, without restarting the game. I cycles the audio interpolation
between Gaussian (the console's own, the default), Cubic (crisper
highs) and Sinc; it only changes what you hear, never the game, and the
choice is saved in audio_interpolation.txt.
On laptops with two graphics cards (NVIDIA Optimus, AMD switchable graphics) the game asks the driver for the dedicated one. If it still runs slowly, set the game's executable to High performance in Windows Settings → System → Display → Graphics.
Saves and updates
The game's own save (the cartridge's battery-backed save) is kept
in build\saves\save.srm.
With Check for updates on start ticked (the default; on the launcher's main
screen, next to Skip launcher on boot), the game asks GitHub for the latest
release when it starts and offers to install a newer one. Accepting closes the
game, downloads the new setup pack, copies it over the install folder and
reopens the setup window: press Generate & rebuild. Nothing is deleted;
build\ (the rebuilt game, saves\, save states, config.ini,
keybinds.ini) and rom.cfg are kept. Untick the box to turn the check off
(saved in update.ini).
Your saves are never lost or broken by an update. In-game saves and save
states made by any release keep working in every later one. Before installing,
the updater copies build\saves\ to save-backups\<date>_before_<version>\
and never deletes those copies; save files are left out of the copy, and if
they changed anyway the backup is put back. Every release after the first is
checked against the one before it with tools/check_update_compat.ps1, which
builds the previous release, makes an in-game save and a save state with it,
installs the new pack with the previous release's own updater and rebuilds; it
fails unless every save file is byte-identical and the new build continues the
old save state.
See CHANGELOG.md for what changed in each release.
Status
Boots through the Nintendo and HAL logos, the opening and the title screen
into the game select and the levels, at full speed with the SA-1 running. The
in-game save is written to save.srm. Most code still runs through the
snesrecomp interpreter; Spring Breeze and the attract demos are checked, the
other games and every boss are not yet verified. See
Porting from here.
Framework patches
patches/ holds changes to the snesrecomp and recomp-ui submodules.
Reapply them after updating the submodules:
git -C snesrecomp apply ../patches/snesrecomp-apu-first-read-timeline.patch
git -C snesrecomp apply ../patches/snesrecomp-audio-interpolation.patch
git -C snesrecomp apply ../patches/snesrecomp-glsl-passprev-and-vao.patch
git -C snesrecomp apply ../patches/snesrecomp-mosaic-frame-model.patch
git -C snesrecomp apply ../patches/snesrecomp-nmi-idle-loop-wai.patch
git -C snesrecomp apply ../patches/snesrecomp-nmi-wai-in-handler.patch
git -C snesrecomp apply ../patches/snesrecomp-raster-oam-and-hdma.patch
git -C snesrecomp apply ../patches/snesrecomp-raster-palette-history.patch
git -C snesrecomp apply ../patches/snesrecomp-shader-forces-opengl.patch
git -C recomp-ui apply ../patches/recomp-ui-host-toggle.patch
snesrecomp-apu-first-read-timeline.patch lets the sound chip run from power
on when the game reads its ports before writing them. Kirby Super Star reads
the sound port once, right after the SA-1 finishes its start-up, and uploads
its sound driver only if the chip's boot ROM answers; the framework started
the sound chip's clock at the first port write, so the read found nothing and
the game waited forever on a black screen.
snesrecomp-raster-palette-history.patch draws each part of the picture with
the palettes it had there. The game reloads palettes at line 168 for the
status bar and puts the stage palettes back in vblank; the renderer drew the
whole field with the palettes left at its end, so every stage took the status
bar's colors.
snesrecomp-raster-oam-and-hdma.patch is the renderer fix shared with the
other ports: per-line sprite tables, HDMA set up in vblank, and vblank writes
kept in their own field. It also counts HDMA's first transfer, made in V=0's
H-blank, as a table line, as the hardware does. The per-line sprite table is
used only for a screen split, a table rewritten before line 200.
snesrecomp-mosaic-frame-model.patch builds the mosaic table on every visible
line. The optimized renderer built it only on line 0, which frame-model hosts
never render, so every line of a mosaic-enabled layer sampled the layer's
first row.
snesrecomp-nmi-idle-loop-wai.patch and snesrecomp-nmi-wai-in-handler.patch
make a WAI halt until the next interrupt, as on hardware, in the main loop
and inside an interrupt handler; without them the interpreter could spin to
its step cap and freeze the screen.
snesrecomp-audio-interpolation.patch adds the Cubic and Sinc audio
interpolation (I key). They resample the dry output only; the echo buffer,
OUTX, pitch modulation and save states stay those of the console's Gaussian
filter, so the game runs identically in every mode.
snesrecomp-glsl-passprev-and-vao.patch fixes two shader bugs: a pass that
reads PassPrev<n> back to the game frame got nothing (ScaleFX drew black),
and switching to no shader mid-game drew a black screen because the shader
path left the plain path's vertex attributes disabled.
snesrecomp-shader-forces-opengl.patch switches the renderer to OpenGL when a
shader is picked, since the presets only run there.
recomp-ui-host-toggle.patch lets a title add one checkbox of its own beside
"Skip launcher on boot"; this project uses it for the update check.
ROM identity
| File | Kirby Super Star (USA).sfc |
| Publisher | Nintendo |
| Developer | HAL Laboratory |
| Year | 1996 |
| Mapping | sa1 |
| Region | USA (North America) |
| Coprocessor | SA-1 |
| CRC32 | 89d0f7dc |
| SHA-256 | 4e095fbbdec4a16b075d7140385ff68b259870ca9e3357f076dfff7f3d1c4a62 |
tools/regen.sh refuses to run against anything else, so a mismatched
revision fails immediately instead of producing subtly wrong output.
Build
git submodule update --init --recursive
bash tools/regen.sh --rom "/path/to/Kirby Super Star (USA).sfc"
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j
The ROM does not have to live in the repository — keeping it on your own
drive is the better habit, and SNESRECOMP_ROM sets the path once for a
shell. Without either, tools/regen.sh finds
Kirby Super Star (USA).sfc at the repo root, then the path
the setup wizard recorded in rom.cfg; .gitignore blocks both from ever
being committed.
tools/regen.sh verifies the ROM, generates src/gen/*.c, and re-syncs
recomp/funcs.h. Re-run it whenever you change anything under recomp/.
The Windows build is a window app: diagnostics go to
KirbySuperStarSNESRecomp.log beside the executable.
-DKSS_CONSOLE=ON brings the console back for debugging.
Run
./build/KirbySuperStarSNESRecomp # launcher picks the ROM
./build/KirbySuperStarSNESRecomp "/path/to/Kirby Super Star (USA).sfc"
With no ROM on the command line the build opens the recomp-ui launcher: a ROM
picker with a verification badge, plus display / audio / input settings. Your
choice is cached in rom.cfg beside the executable, so the next launch opens
on it and "Skip launcher on boot" makes it immediate.
Either way the ROM is checked against the digests above before anything boots — a dump that could not have produced this build is refused at the door rather than mis-executing ten frames in.
Layout
| Path | What lives there |
|---|---|
recomp/ | Analysis input: bank*.cfg, symbols.toml, generated funcs.h |
rom_identity.txt | ROM digests — read by the build, tools/regen.sh and CI |
src/ | Host code you own: main.c, game_rtl.c, kss_update.c |
src/gen/ | Generated C. Never committed — regenerate locally |
assets/shaders/ | Scanline, CRT and upscaler presets for the launcher |
patches/ | Changes to the framework submodules (see above) |
snesrecomp/ | Framework submodule (owns lib/recomp-net, lib/retcomm-rbengine) |
tools/ | regen.sh — the ROM → C pipeline; check_update_compat.ps1; import_libretro_shaders.py |
scripts/ | package_release.sh — player-facing zip |
framework_pins.txt | Exact framework commits this project was scaffolded against |
Porting from here
The scaffold stops where the game-specific work starts. In rough order:
- Make it boot.
src/game_rtl.cholds the frame driver. It starts on the framework's beam-aligned driver (snesrecomp/runner/src/beam_frame_driver.h): one frame per PPU field, interrupts taken where the beam latches them, the field rasterized from the raster journal. - Name things. Add entries to
recomp/symbols.tomlas you identify routines, then re-runtools/regen.sh. Setemit = trueto promote one into ahead-of-time analysis; leave it false to keep it interpreted. Seerecomp/README.md. - Resolve dispatch misses. After every run, deal with unresolved indirect targets before anything else — they are the reason a port diverges, and they are cheap to fix early.
- Never synthesise a result to get past uncovered code, and never edit
src/gen/by hand. Fix the config or the framework and regenerate.
Multiplayer
Two players: the second controller takes over Kirby's helper.
License
This project's own source is under the MIT license in LICENSE. The
framework carries its own terms (PolyForm Noncommercial 1.0.0) — see
snesrecomp/LICENSE and snesrecomp/THIRD_PARTY_ATTRIBUTION.md; the changes
in patches/ apply to that framework and fall under its terms. The shaders
under assets/shaders/_libretro/ come from libretro/glsl-shaders and keep each
author's license in their file headers. None of these cover the game data,
which is not distributed here.
Enjoying Kirby Super Star Recomp? ☕ Buy me a coffee to help bring the next SNES game to native Recomp.