Loading...
Searching...
No Matches
main.c File Reference

SNES Super Scope light gun detection, calibration, and firing. More...

#include <snes.h>
#include <snes/input.h>
#include <snes/text.h>
#include <snes/dma.h>

Macros

#define STATE_CALIBRATE   1
 Asking player to shoot screen center for aim offset calibration.
 
#define STATE_DETECT   0
 Waiting for Super Scope to be connected to port 2.
 
#define STATE_READY   2
 Calibrated and tracking fire events; placing red dot markers.
 

Functions

static void clearBottom (void)
 Clear the bottom 4 rows of the text overlay (rows 24-27).
 
static void hideDot (void)
 Hide the red dot marker sprite by moving it off-screen.
 
int main (void)
 Main entry point – Super Scope detection, calibration, and fire tracking.
 
static void showDot (u16 x, u16 y)
 Show the red dot marker at the given screen coordinates.
 

Variables

u8 aim_target_map []
 Aim target tilemap (32x32 BG2 layout) from data.asm.
 
u8 aim_target_map_end []
 
u8 aim_target_pal []
 Aim target palette (BGR555) from data.asm.
 
u8 aim_target_pal_end []
 
u8 aim_target_tiles []
 Aim target background tile data (2bpp, crosshair pattern) from data.asm.
 
u8 aim_target_tiles_end []
 
u8 sprites_pal []
 Sprite palette (BGR555) from data.asm.
 
u8 sprites_pal_end []
 
u8 sprites_tiles []
 Sprite tile data (red dot marker, 4bpp) from data.asm.
 
u8 sprites_tiles_end []
 

Detailed Description

SNES Super Scope light gun detection, calibration, and firing.

Demonstrates the SNES Super Scope (light gun) peripheral connected to controller port 2. The Super Scope works by detecting the CRT beam position when the trigger is pulled, returning X/Y screen coordinates via the auto-joypad registers. Because the sensor relies on CRT timing, a calibration step is needed to correct for aiming offset.

The example uses a three-state machine: DETECT waits for the Super Scope to be connected, CALIBRATE asks the player to shoot the screen center so the library can compute the aim offset, and READY tracks fire events and marks the hit position with a red dot sprite.

Video setup: Mode 0 with BG1 (text overlay) and BG2 (crosshair target background for calibration), plus OBJ sprites for the red dot marker.

SNES Concepts
  • Super Scope peripheral detection and calibration flow
  • Light gun coordinate reading (scopeGetX / scopeGetY)
  • Button polling for FIRE, PAUSE, and CURSOR buttons
  • Multi-layer Mode 0 with text on BG1 and graphics on BG2
  • Sprite positioning from light gun coordinates
What to Observe
  • "Connect SuperScope to Port 2" message on startup
  • After connection, a crosshair target for calibration
  • Shooting places a red dot at the hit position
  • PAUSE button returns to calibration; CURSOR transitions to play
Modules Used
console, input, sprite, dma, text, background
See also
input.h, sprite.h, dma.h, text.h

Macro Definition Documentation

◆ STATE_CALIBRATE

#define STATE_CALIBRATE   1

Asking player to shoot screen center for aim offset calibration.

◆ STATE_DETECT

#define STATE_DETECT   0

Waiting for Super Scope to be connected to port 2.

◆ STATE_READY

#define STATE_READY   2

Calibrated and tracking fire events; placing red dot markers.

Function Documentation

◆ clearBottom()

static void clearBottom ( void  )
static

Clear the bottom 4 rows of the text overlay (rows 24-27).

Used to erase status messages when transitioning between states (detect, calibrate, ready).

◆ hideDot()

static void hideDot ( void  )
static

Hide the red dot marker sprite by moving it off-screen.

Y coordinate OAM_Y_OFFSCREEN (224) is below the NTSC visible area, so the SNES PPU will not render this sprite. This is cheaper than disabling the sprite via the OAM high table.

◆ main()

int main ( void  )

Main entry point – Super Scope detection, calibration, and fire tracking.

Implements a three-state machine:

  • STATE_DETECT: polls scopeInit() / scopeIsConnected() each frame until the Super Scope is detected on controller port 2.
  • STATE_CALIBRATE: displays a crosshair target on BG2 and waits for the player to shoot the center. scopeCalibrate() records the aim offset so subsequent coordinate readings are accurate.
  • STATE_READY: tracks FIRE events, reads calibrated X/Y via scopeGetX() / scopeGetY(), and places a red dot sprite at the hit position. The PAUSE button returns to calibration for re-aiming.

The fire_armed flag prevents stale FIRE events from the previous state from triggering immediately on state entry.

Returns
0 (never reached – infinite game loop)

◆ showDot()

static void showDot ( u16  x,
u16  y 
)
static

Show the red dot marker at the given screen coordinates.

Updates sprite 0's X/Y in the OAM low table and signals the NMI handler to DMA the OAM buffer to the PPU next VBlank.

Parameters
xScreen X coordinate (0-255)
yScreen Y coordinate (0-223 for visible area)

Variable Documentation

◆ aim_target_map

u8 aim_target_map[]
extern

Aim target tilemap (32x32 BG2 layout) from data.asm.

◆ aim_target_map_end

u8 aim_target_map_end[]

◆ aim_target_pal

u8 aim_target_pal[]
extern

Aim target palette (BGR555) from data.asm.

◆ aim_target_pal_end

u8 aim_target_pal_end[]

◆ aim_target_tiles

u8 aim_target_tiles[]
extern

Aim target background tile data (2bpp, crosshair pattern) from data.asm.

◆ aim_target_tiles_end

u8 aim_target_tiles_end[]

◆ sprites_pal

u8 sprites_pal[]
extern

Sprite palette (BGR555) from data.asm.

◆ sprites_pal_end

u8 sprites_pal_end[]

◆ sprites_tiles

u8 sprites_tiles[]
extern

Sprite tile data (red dot marker, 4bpp) from data.asm.

◆ sprites_tiles_end

u8 sprites_tiles_end[]