OpenSNES
Modern Open-Source SNES Development SDK
Loading...
Searching...
No Matches
main.c File Reference

Game math & UI, rung — panel HUD: a status box that survives a dialog. More...

#include <snes.h>
#include <snes/panel.h>
#include <snes/input.h>

Macros

#define BG1_CHR   0x0000
#define BG1_MAP   0x1000
#define BG2_CHR   0x2000
#define BG2_MAP   0x4400
#define BORDER_IDX   2 /* box border */
#define BOX_PAL   1
#define DLG_H   7
#define DLG_W   24
#define DLG_X   4
#define DLG_Y   20
#define EMPTY_IDX   4 /* empty-heart grey */
#define FILL_IDX   1 /* box interior */
#define HEART_IDX   3 /* heart red */
#define HUD_H   3
#define HUD_W   14
#define HUD_X   1
#define HUD_Y   1
#define MAX_HP   5
#define SHEET_BASE   1 /* top-left corner of the 3x3 border */
#define SHEET_STRIDE   3
#define TILE_BLANK   0
#define TILE_HEART   10 /* icons live past the 9-slice */
#define TILE_HEART_EMPTY   11

Functions

static void build_border (u8 top, u8 bottom, u8 left, u8 right)
 Build one 9-slice border tile: border on the named edges, fill else.
static void build_heart (u8 filled)
 Build a heart icon on the box-fill background (filled or outline).
static void build_scene (void)
 A colourful BG1 scene so the HUD clearly floats over content.
static void build_sheet (void)
 Build the whole BG2 sheet: blank, 9-slice, two heart icons.
static void draw_hearts (void)
 Redraw the heart row inside the HUD from hero_hp.
static void encode_4bpp (void)
 Pack px[] (8x8 palette indices) into a 4bpp planar tile.
static void flush_hud_row (void)
 Push ONLY the HUD's heart row to VRAM — a small VBlank-safe DMA.
int main (void)
static void put_tile (u16 tile)
 Upload the just-encoded tile to a tile slot in BG2's char space.

Variables

u8 dialog_shown
 Probe oracle: 1 while the dialog box is open.
u8 hero_hp
 Probe oracle: current hearts shown (0..MAX_HP).
static u16 panel_map [32 *32]
 The panel tilemap — caller-owned (the module never allocates 2 KB).
static u8 px [64]
 Scratch: one 8x8 tile as pixel indices, then packed to 4bpp.
static u8 tilebuf [32]
static const Panel ui
 The panel: HUD + dialog share this one layer and one upload.

Detailed Description

Game math & UI, rung — panel HUD: a status box that survives a dialog.

Every game needs furniture: a status bar with hearts and a coin count, a dialog box that opens over the world and closes again. Both are the same primitive — a 9-slice panel, a bordered box stamped from a 3x3 tile sheet (four corners, four edges, one fill) onto a background layer. The panel module does the stamping; you own the tilemap.

Its whole point is on show here: the HUD and the dialog live in ONE tilemap on ONE layer. Opening the dialog (panelDraw + panelFlush) and closing it (panelClear + panelFlush) never disturbs the HUD.

panelFlush() uploads the whole 2 KB map under FORCED BLANK, which briefly blanks the screen — fine for a structural change like a dialog box, but far too heavy to run every time a heart changes. So the hearts, which change often, upload only their own 64-byte tilemap row with an ordinary VBlank DMA (flush_hud_row) — no forced blank, no flicker. The rule: panelFlush for structure, a small VBlank DMA for frequent HUD tweaks.

The border and heart icons are generated in C — zero assets. Tile 0 is left transparent (that is what panelInit() stamps everywhere), so the colourful BG1 shows through wherever no panel has been drawn.

ROM mode: LoROM (project default).

Controls
  • B: lose a heart · A: gain one (small VBlank DMA of the heart row)
  • START: toggle the dialog box (panelFlush; the HUD stays put)
SNES Concepts
  • 9-slice stamping: panelDraw() picks corner/edge/fill from the sheet by position; panelPut() drops a single sheet tile (an icon) into the box
  • Several panels, one layer, one upload — the module's reason to exist
  • panelFlush() uploads under real forced blank (INIDISP bit 7): safe for 2 KB but it blanks briefly, so use it for structural changes; push a frequently-updated HUD row with a small ordinary VBlank DMA instead
What to Observe
A HUD box with hearts sits over a colourful background. A/B change the hearts; START opens/closes a dialog box lower down without touching the HUD. hero_hp and dialog_shown are the probe oracles.
Modules Used
console, dma, background, panel, input
See also
lib/include/snes/panel.h — panelInit/Draw/Put/Clear/Flush

Macro Definition Documentation

◆ BG1_CHR

#define BG1_CHR   0x0000

BG1 scene tiles

◆ BG1_MAP

#define BG1_MAP   0x1000

BG1 tilemap

◆ BG2_CHR

#define BG2_CHR   0x2000

BG2 panel sheet tiles

◆ BG2_MAP

#define BG2_MAP   0x4400

BG2 panel tilemap (uploaded by panelFlush)

◆ BORDER_IDX

#define BORDER_IDX   2 /* box border */

◆ BOX_PAL

#define BOX_PAL   1

◆ DLG_H

#define DLG_H   7

◆ DLG_W

#define DLG_W   24

◆ DLG_X

#define DLG_X   4

◆ DLG_Y

#define DLG_Y   20

◆ EMPTY_IDX

#define EMPTY_IDX   4 /* empty-heart grey */

◆ FILL_IDX

#define FILL_IDX   1 /* box interior */

◆ HEART_IDX

#define HEART_IDX   3 /* heart red */

◆ HUD_H

#define HUD_H   3

◆ HUD_W

#define HUD_W   14

◆ HUD_X

#define HUD_X   1

◆ HUD_Y

#define HUD_Y   1

◆ MAX_HP

#define MAX_HP   5

◆ SHEET_BASE

#define SHEET_BASE   1 /* top-left corner of the 3x3 border */

◆ SHEET_STRIDE

#define SHEET_STRIDE   3

◆ TILE_BLANK

#define TILE_BLANK   0

◆ TILE_HEART

#define TILE_HEART   10 /* icons live past the 9-slice */

◆ TILE_HEART_EMPTY

#define TILE_HEART_EMPTY   11

Function Documentation

◆ build_border()

void build_border ( u8 top,
u8 bottom,
u8 left,
u8 right )
static

Build one 9-slice border tile: border on the named edges, fill else.

Parameters
top,bottom,left,right1 if this tile carries that edge.

◆ build_heart()

void build_heart ( u8 filled)
static

Build a heart icon on the box-fill background (filled or outline).

◆ build_scene()

void build_scene ( void )
static

A colourful BG1 scene so the HUD clearly floats over content.

< BG1 scene tiles

< BG1 tilemap

◆ build_sheet()

void build_sheet ( void )
static

Build the whole BG2 sheet: blank, 9-slice, two heart icons.

◆ draw_hearts()

void draw_hearts ( void )
static

Redraw the heart row inside the HUD from hero_hp.

◆ encode_4bpp()

void encode_4bpp ( void )
static

Pack px[] (8x8 palette indices) into a 4bpp planar tile.

◆ flush_hud_row()

void flush_hud_row ( void )
static

Push ONLY the HUD's heart row to VRAM — a small VBlank-safe DMA.

The hearts change often (every hit), so they must not pay panelFlush()'s 2 KB forced-blank cost — that would blank the top of the screen for a frame on every change. One tilemap row is 64 bytes, which fits the VBlank budget with room to spare, so we upload just that row with no forced blank. panelFlush() stays for structural changes (opening the dialog).

< BG2 panel tilemap (uploaded by panelFlush)

◆ main()

int main ( void )

< BG1 scene tiles

< BG1 tilemap

< BG2 panel sheet tiles

< BG2 panel tilemap (uploaded by panelFlush)

◆ put_tile()

void put_tile ( u16 tile)
static

Upload the just-encoded tile to a tile slot in BG2's char space.

< BG2 panel sheet tiles

Variable Documentation

◆ dialog_shown

u8 dialog_shown

Probe oracle: 1 while the dialog box is open.

◆ hero_hp

u8 hero_hp

Probe oracle: current hearts shown (0..MAX_HP).

◆ panel_map

u16 panel_map[32 *32]
static

The panel tilemap — caller-owned (the module never allocates 2 KB).

◆ px

u8 px[64]
static

Scratch: one 8x8 tile as pixel indices, then packed to 4bpp.

◆ tilebuf

u8 tilebuf[32]
static

◆ ui

const Panel ui
static
Initial value:
= {
0x4400 ,
1 ,
3 ,
1 ,
1,
}
static u16 panel_map[32 *32]
The panel tilemap — caller-owned (the module never allocates 2 KB).
Definition main.c:97

The panel: HUD + dialog share this one layer and one upload.