Screenshot
Screen brightness transitions for fade in/out effects.
Learning Objectives
After this lesson, you will understand:
- How SNES screen brightness control works
- Creating smooth fade transitions
- Different fade speeds and styles
- Using fades for scene transitions
Prerequisites
- Completed background examples
- Understanding of VBlank timing
What This Example Does
Demonstrates multiple fade effects:
- Fade from black to full brightness
- Fade from full brightness to black
- Fast and slow fade speeds
- Button-triggered transitions
Frame 1: ████████████████ (Black)
Frame 5: ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ (25%)
Frame 10: ░░░░░░░░░░░░░░░░ (50%)
Frame 15: ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ (75%)
Frame 20: [Full Image] (100%)
Controls:
- Any button: Advance to next fade effect
Code Type
C with Direct Register Access
| Component | Type |
| Background setup | Library functions |
| Brightness control | Direct register (REG_INIDISP) |
| Fade timing | Frame counting with WaitForVBlank() |
| Input detection | Direct register access |
INIDISP Register
The INIDISP register ($2100) controls screen brightness:
Bits 0-3: Brightness level (0-15)
Bit 4: Force blank (1 = screen off)
Bits 5-7: Unused
| Value | Effect |
| $00 | Brightness 0 (black, screen on) |
| $0F | Brightness 15 (full) |
| $80 | Force blank (screen completely off) |
| $8F | Force blank at full brightness |
Basic Fade Implementation
Fade In (Black to Full)
}
}
}
void WaitForVBlank(void)
Wait for next VBlank period.
static u8 i
Definition main.c:156
static u16 bx
Definition main.c:159
#define REG_INIDISP
Display control (W)
Definition registers.h:49
unsigned char u8
8-bit unsigned integer (0 to 255)
Definition types.h:46
Fade Out (Full to Black)
Fade Speeds
Different speeds for different purposes:
| Speed | Frames per step | Total frames | Duration |
| 1 | 1 | 15 | 0.25 sec |
| 2 | 2 | 30 | 0.5 sec |
| 4 | 4 | 60 | 1.0 sec |
| 8 | 8 | 120 | 2.0 sec |
Quick Flash
Scene Transition Pattern
}
#define INIDISP_FORCE_BLANK
Definition registers.h:424
Build & Run
cd $OPENSNES_HOME
make -C examples/graphics/effects/fading
Then open fading.sfc in your emulator (Mesen2 recommended).
Files
| File | Purpose |
main.c | Fade logic and demo sequence |
data.asm | Background graphics |
Makefile | Build configuration (LIB_MODULES := console sprite dma input background) |
Exercises
Exercise 1: Smooth Fade
Create smoother fades using sub-frame timing (though limited by 16 brightness levels):
Exercise 2: Directional Wipe
Combine with window masking for a wipe effect instead of fade.
Exercise 3: Color Fade
Use color math to fade to a specific color instead of black:
void colorMathSetFixedColor(u8 r, u8 g, u8 b)
Set fixed color for blending.
static u16 b
Definition main.c:157
Exercise 4: Pulse Effect
Create a pulsing brightness effect:
Technical Notes
Force Blank vs Brightness 0
- Brightness 0: Screen shows black, but PPU still renders
- Force Blank: PPU stops rendering, VRAM access is safe
Use force blank when updating graphics, brightness 0 for visual fades.
Fade During Gameplay
For in-game fades without stopping action:
- Use force blank only briefly for VRAM updates
- Fade brightness while game continues
- Game logic runs normally during fade
Alternative: Palette Fade
Instead of hardware brightness, modify palette colors:
for (
u8 i = 0;
i < 256;
i++) {
}
void dmaCopyCGram(u8 *source, u16 startColor, u16 size)
Copy palette data to CGRAM (PVSnesLib compatible)
u8 palette[]
Full 256-color palette for BG and sprite layers (512 bytes)
This allows fading specific layers independently.
What's Next?
Mosaic: Mosaic Example - Pixelation transitions
Parallax: Parallax Scrolling - Multi-speed scrolling with HDMA