Small SNES homebrew project built with PVSnesLib. The game ROM is generated as snesgame2.sfc and can be run in a SNES emulator after building.
- C for game logic in
src/main.c - PVSnesLib for the SNES SDK and build rules
- GNU Make on Linux or WSL (Ubuntu 24.04 or later)
- PVSnesLib graphics conversion tools during
make - Python helper scripts in
tools/for regenerating source BMP art
src/main.c: main game codeMakefile: build rules and graphics conversion stepstools/: helper scripts to regenerate some sprite BMP assets*.bmp/pvsneslibfont.png: authored source graphics used by the build*.pic,*.pal,*.inc,*_data.as: generated SNES graphics data consumed by the gamesnesgame2.sfc: built ROM output
The build targets Linux or WSL (Ubuntu 24.04 or later) with GNU Make. There is no native Windows build — on Windows, run the build inside WSL.
Install PVSnesLib and set PVSNESLIB_HOME to point at it, using a Unix-style
path. Add it to your shell profile (e.g. ~/.bashrc) so every shell has it:
export PVSNESLIB_HOME=/opt/pvsneslibThe Makefile reads PVSNESLIB_HOME and stops with an error if it isn't set.
Needed to run the helper scripts in tools/ that regenerate some BMP assets.
They use only the standard library (no pip install required).
Any emulator that can load .sfc ROMs should work.
The build works in two stages:
- Convert image assets into SNES graphics data.
- Compile and link the game into
snesgame2.sfc.
The Makefile target flow is:
all: artifacts snesgame2.sfcartifacts groups the asset-conversion steps (bitmaps, musics, brrsound).
The bitmaps target regenerates SNES-ready graphics data from the source images:
pvsneslibfont.png->pvsneslibfont.pic,pvsneslibfont.palsprites.bmp->sprites.pic,sprites.palenemy.bmp->enemy.pic,enemy.paltac2.bmp->tac2.pic,tac2.palbullet.bmp->bullet.pic,bullet.pal
From those assets, the PVSnesLib build rules generate the final ROM.
With PVSNESLIB_HOME set (see Required Tools), build from the project directory:
makeTo rebuild just the converted assets without linking the ROM:
make artifactsTo remove all build output and generated asset data:
make cleanmake/make all: convert assets, compile code, and producesnesgame2.sfcmake artifacts: convert source art/sound into SNES data, without linking the ROMmake clean: remove the ROM, build intermediates, and generated asset data through the PVSnesLib clean rules
This project keeps source art in standard image formats and converts them during the build.
sprites.bmp: player sprite sheetenemy.bmp: enemy sprite sheet (Genesis console; one hit to destroy)tac2.bmp: tough enemy sprite (TAC-2 joystick; takes three hits to destroy)bullet.bmp: bullet spritepvsneslibfont.png: font image
The conversion step produces files such as:
.pic: tile graphics.pal: palettes.inc: include symbols for the game code*_data.as: assembler data blobs used by the linker
These generated files are already present in the repository, but they can be regenerated by rebuilding.
The Python scripts in tools/ are not part of the normal make target. They are helper utilities for regenerating the source BMP files before running the build. They share tools/snesbmp.py (a small standard-library helper that draws onto an indexed canvas and writes the 8bpp BMP), and they use only the Python standard library, so they run the same on Linux and WSL.
- Rebuilds
sprites.bmp - Preserves an original backup at
tools/sprites_src.bmp - Downscales the player art to roughly
21x21inside a32x32sprite cell
Run it with:
python3 tools/make_player_bmp.py- Generates
enemy.bmp - Creates an 8bpp
32x32enemy sprite with a fixed palette - Downscales the art to roughly
21x21inside a32x32sprite cell
Run it with:
python3 tools/make_enemy_bmp.py- Generates
tac2.bmp - Creates an 8bpp
32x32sprite of a Suncom TAC-2 arcade joystick (red ball-top stick, chrome shaft, black base with a red fire button) - Draws the art in the top-left
21x21of the32x32cell so it lines up with the enemy hit-box - This is the tougher enemy: it takes three hits to destroy (a screen-clearing bomb still flattens it in one), descends more slowly, and is worth more points
Run it with:
python3 tools/make_tac2_bmp.py- Generates
bullet.bmp - Creates an 8bpp
8x8bullet sprite with a small fixed palette
Run it with:
python3 tools/make_bullet_bmp.pyAfter running any of these scripts, rebuild the project so the .bmp changes are converted into SNES asset data.
Successful builds produce:
snesgame2.sfc
Other intermediate files such as object files, symbol files, and converted graphics data may also be produced or refreshed.
If make stops immediately with a message about PVSNESLIB_HOME, export the
variable so it points at your PVSnesLib install (a Unix-style path), e.g.
export PVSNESLIB_HOME=/opt/pvsneslib, and add it to your shell profile so it
persists.
PVSNESLIB_HOME must be a Unix-style path (PVSnesLib's build rules reject paths
containing a backslash). Under WSL, point it at a Linux path or a /mnt/c/...
mount, not a C:\... path.
If you edited or regenerated a BMP or the font PNG, rebuild the ROM so the graphics conversion step runs again.
python3 tools/make_enemy_bmp.py
python3 tools/make_bullet_bmp.py
makeIf you did not change the source art, only make is needed.