Common issues and their solutions.
Build Issues
"OPENSNES not defined" or "No rule to make target 'common.mk'"
Cause: The Makefile can't find the OpenSNES installation.
Fix: Set OPENSNES in your Makefile or set the environment variable:
# Option 1: Set in Makefile (recommended for project portability)
OPENSNES := /path/to/opensnes
# Option 2: Set environment variable
export OPENSNES_HOME=/path/to/opensnes
Empty <tt>compiler/</tt> directories or "cc65816 not found"
Cause: Submodules weren't cloned.
Fix:
cd /path/to/opensnes
git submodule update --init --recursive
make compiler
"wla-65816: command not found"
Cause: Compiler toolchain not built.
Fix:
cd /path/to/opensnes
make compiler
"clang: command not found" or "cc: command not found"
Cause: Missing host C compiler.
Fix (by platform):
# macOS
xcode-select --install
# Ubuntu/Debian
sudo apt install clang
# Fedora
sudo dnf install clang
# Windows MSYS2 (UCRT64)
pacman -S mingw-w64-ucrt-x86_64-clang
Build fails with "unhandled op: XXX"
Cause: The QBE backend doesn't support a specific operation (usually 32-bit or complex expressions).
Fix: Simplify your code:
static u16 b
Definition main.c:157
static u16 bx
Definition main.c:159
static u16 a
Definition main.c:157
static u16 c
Definition main.c:157
unsigned int u32
32-bit unsigned integer (0 to 4294967295)
Definition types.h:66
unsigned short u16
16-bit unsigned integer (0 to 65535)
Definition types.h:52
Static variables with initializers
Initialized static variables now work correctly:
unsigned char u8
8-bit unsigned integer (0 to 255)
Definition types.h:46
The CopyInitData routine in crt0.asm copies initial values from ROM to RAM before main() is called.
Runtime Issues (Black Screen / Crash)
ROM loads but screen is black
This is the most common issue. Causes and fixes:
1. Missing setScreenOn()
void setScreenOn(void)
Enable screen display.
2. No VBlank loop
while (1) {
}
void WaitForVBlank(void)
Wait for next VBlank period.
3. Console not initialized
void consoleInit(void)
Initialize SNES hardware.
4. Memory overlap (WRAM mirror bug)
Bank $00 addresses $0000-$1FFF mirror Bank $7E addresses $7E:0000-$1FFF. If you have variables in both ranges, they'll overwrite each other.
Diagnose:
python3 devtools/symmap/symmap.py --check-overlap game.sym
Fix: The library uses ORGA $0300 to avoid the overlap zone.
ROM runs but crashes after a few seconds
Causes:
- Stack overflow - Too many function calls or large local arrays
- DMA during active display - Only do DMA in VBlank
- Uninitialized pointers - C doesn't zero local variables
Debug:
- Use Mesen's debugger to see where it crashes
- Check the call stack depth
- Look for NULL pointer dereferences
Sprites don't appear
Checklist:
oamSet(0, x, y, 3, 0, 0, 0, 0);
u8 sprite_pal_end[]
Definition main.c:46
u8 sprite_pal[]
Palette for the character sprite (16 colors, 4bpp)
void oamInitGfxSet(u8 *tileSource, u16 tileSize, u8 *tilePalette, u16 paletteSize, u8 paletteEntry, u16 vramAddr, u8 oamSize)
Initialize sprite graphics and palette (PVSnesLib compatible)
void oamSet(u16 id, u16 x, u16 y, u16 tile, u16 palette, u16 priority, u16 flags)
Set sprite properties.
void oamInit(u16 size, u16 tile_base)
Initialize the sprite (OAM) system.
#define OBJ_SIZE8_L16
Sprite size indices (for oamInit, oamInitGfxSet)
Definition sprite.h:49
Controller input not working
Checklist:
Audio not playing
For basic audio:
void audioInit(void)
Initialize the audio system.
u8 audioPlaySample(u8 sampleId)
Play a sample with default settings.
For SNESMOD:
while (1) {
}
void snesmodSetSoundbank(u8 bank)
Set the soundbank bank number.
void snesmodInit(void)
Initialize SNESMOD audio engine.
void snesmodPlay(u8 startPosition)
Start module playback.
void snesmodLoadModule(u16 moduleId)
Load a module from the soundbank.
void snesmodProcess(void)
Process audio commands.
Graphics Issues
Wrong colors / garbled palette
Cause: BGR555 format mismatch.
SNES uses BGR555 (5 bits blue, 5 green, 5 red), not RGB. Use gfx4snes to convert PNGs correctly:
gfx4snes -i sprite.png -o sprite
Tiles appear corrupted
Causes:
- Wrong tile format (2bpp vs 4bpp vs 8bpp)
- VRAM address overlap
- DMA transfer size mismatch
Check your graphics mode:
void bgInitTileSet(u8 bgNumber, u8 *tileSource, u8 *tilePalette, u8 paletteEntry, u16 tileSize, u16 paletteSize, u16 colorMode, u16 vramAddr)
Initialize tileset with tiles and palette.
#define BG_MODE1
Definition video.h:28
void setMode(u8 mode, u8 flags)
Set background mode.
Scrolling is jerky
Cause: Updating scroll registers outside VBlank.
Fix:
while (1) {
}
void bgSetScroll(u8 bg, u16 x, u16 y)
Set background scroll position.
Memory Issues
"ROM too large" or linker errors about size
Cause: Too much data in your ROM.
Check ROM size:
Solutions:
- Compress graphics
- Use smaller audio samples
- Split into multiple banks (advanced)
Variables have wrong values
Check symbol placement:
grep "my_variable" game.sym
- Good (RAM):
00:0234 my_variable
- Bad (ROM):
00:8234 my_variable
If it's in ROM ($8000+), you can't write to it.
Getting More Help
Diagnostic Commands
# Check for memory overlaps
python3 devtools/symmap/symmap.py --check-overlap game.sym
# View symbol map
cat game.sym | grep "variable_name"
# Inspect ROM header
xxd -s 0x7FC0 -l 32 game.sfc
# Check ROM size
ls -la game.sfc
Using Mesen Debugger
- Load ROM in Mesen
- Tools → Debugger
- Set breakpoint at your code
- Step through and watch registers/memory
Reporting Bugs
Include in your issue:
- OpenSNES version (
git rev-parse HEAD)
- OS and compiler version
- Minimal code that reproduces the issue
- Error messages (full output)
- What you expected vs what happened