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

Text — proportional text composed at the pixel in a 2bpp layer. More...

#include <snes.h>
#include <snes/tile.h>
#include <snes/string.h>

Macros

#define COLS   20 /* the layer: 20 x 8 tiles = 160 x 64 pixels */
#define LAYER_VRAM   0x1000 /* word address of the layer's tile 0 */
#define MAP_COL   6 /* where the layer sits on the 32 x 32 map */
#define MAP_ROW   10
#define MAP_VRAM   0x0400
#define PITCH   6 /* pixels from one glyph to the next */
#define ROWS   8
#define TILES   (COLS * ROWS)

Functions

static void build_glyphs (void)
static void compose (void)
static void draw_text (const char *s, u16 x, u16 y)
static u8 glyph_of (char c)
int main (void)
static void place_tiles (void)

Variables

static const u8 font5x7 [36][7]
static FAR u8 glyphs [36][16]
static FAR u8 layer [(20 *8) *16]
u16 layer_sum
static const u8 palette []
u16 presses
static u16 upload
u16 x_off

Detailed Description

Text — proportional text composed at the pixel in a 2bpp layer.

The text module puts one glyph per tile, on the tile grid. A game that wants a narrow font at a 6-pixel pitch, or a label at any x and y, composes its text itself: a 2bpp tile layer kept in RAM, each glyph ORed into it at a pixel offset, the layer sent to VRAM when it changes. The primitive is tileBlitGlyph2bpp(): it puts rows of a glyph into one tile and the tile to its right, shifted by 0 to 7 pixels. A glyph placed at (x, y) touches up to four tiles — the row of tiles holding y and the one below — so two calls cover it, one per tile row. Nothing here is an asset: a 5x7 font is declared as bits and turned into 2bpp glyphs at boot.

SNES Concepts
  • A 2bpp tile is 16 bytes, planes 0 and 1 interleaved per row; a layer of N tiles is N x 16 bytes, and tile n of the layer is tile n of the sheet
  • The tilemap only places tiles: the pixels come from the layer, so text at any position is a matter of writing the right bytes of the right tiles
  • A glyph at x covers tile x / 8 and, shifted by x % 8, the tile after it; at y it covers rows y % 8 to 7 of one tile row and 0 to y % 8 - 1 of the next
  • The layer lives in FAR RAM (2.5 KB) and is cleared with memset() before a new layout; the upload is split over two VBlanks (1280 bytes each)
What to Observe
  • Four lines of white text at a 6-pixel pitch, none aligned on the tile grid (y = 5, 21, 38, 51)
  • Press A: every line moves one pixel to the right (six steps, then back), the glyphs crossing tile boundaries as they go
Modules Used
console, dma, background, input, tile, string
See also
tile.h, string.h, text.h, examples/fundamentals/text_glyphs

Macro Definition Documentation

◆ COLS

#define COLS   20 /* the layer: 20 x 8 tiles = 160 x 64 pixels */

◆ LAYER_VRAM

#define LAYER_VRAM   0x1000 /* word address of the layer's tile 0 */

◆ MAP_COL

#define MAP_COL   6 /* where the layer sits on the 32 x 32 map */

◆ MAP_ROW

#define MAP_ROW   10

◆ MAP_VRAM

#define MAP_VRAM   0x0400

◆ PITCH

#define PITCH   6 /* pixels from one glyph to the next */

◆ ROWS

#define ROWS   8

◆ TILES

#define TILES   (COLS * ROWS)

Function Documentation

◆ build_glyphs()

void build_glyphs ( void )
static

◆ compose()

void compose ( void )
static

◆ draw_text()

void draw_text ( const char * s,
u16 x,
u16 y )
static

Compose a string into the layer at pixel (x, y): two calls per glyph.

◆ glyph_of()

u8 glyph_of ( char c)
static

◆ main()

int main ( void )

◆ place_tiles()

void place_tiles ( void )
static

Place the layer's tiles on the map, in order, and blank everywhere else.

Variable Documentation

◆ font5x7

const u8 font5x7[36][7]
static
Initial value:
= {
{0x0E, 0x11, 0x11, 0x1F, 0x11, 0x11, 0x11}, {0x1E, 0x11, 0x11, 0x1E, 0x11, 0x11, 0x1E},
{0x0E, 0x11, 0x10, 0x10, 0x10, 0x11, 0x0E}, {0x1E, 0x11, 0x11, 0x11, 0x11, 0x11, 0x1E},
{0x1F, 0x10, 0x10, 0x1E, 0x10, 0x10, 0x1F}, {0x1F, 0x10, 0x10, 0x1E, 0x10, 0x10, 0x10},
{0x0E, 0x11, 0x10, 0x17, 0x11, 0x11, 0x0F}, {0x11, 0x11, 0x11, 0x1F, 0x11, 0x11, 0x11},
{0x0E, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0E}, {0x07, 0x02, 0x02, 0x02, 0x02, 0x12, 0x0C},
{0x11, 0x12, 0x14, 0x18, 0x14, 0x12, 0x11}, {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1F},
{0x11, 0x1B, 0x15, 0x15, 0x11, 0x11, 0x11}, {0x11, 0x11, 0x19, 0x15, 0x13, 0x11, 0x11},
{0x0E, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0E}, {0x1E, 0x11, 0x11, 0x1E, 0x10, 0x10, 0x10},
{0x0E, 0x11, 0x11, 0x11, 0x15, 0x12, 0x0D}, {0x1E, 0x11, 0x11, 0x1E, 0x14, 0x12, 0x11},
{0x0F, 0x10, 0x10, 0x0E, 0x01, 0x01, 0x1E}, {0x1F, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04},
{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0E}, {0x11, 0x11, 0x11, 0x11, 0x11, 0x0A, 0x04},
{0x11, 0x11, 0x11, 0x15, 0x15, 0x15, 0x0A}, {0x11, 0x11, 0x0A, 0x04, 0x0A, 0x11, 0x11},
{0x11, 0x11, 0x11, 0x0A, 0x04, 0x04, 0x04}, {0x1F, 0x01, 0x02, 0x04, 0x08, 0x10, 0x1F},
{0x0E, 0x11, 0x13, 0x15, 0x19, 0x11, 0x0E}, {0x04, 0x0C, 0x04, 0x04, 0x04, 0x04, 0x0E},
{0x0E, 0x11, 0x01, 0x02, 0x04, 0x08, 0x1F}, {0x1F, 0x02, 0x04, 0x02, 0x01, 0x11, 0x0E},
{0x02, 0x06, 0x0A, 0x12, 0x1F, 0x02, 0x02}, {0x1F, 0x10, 0x1E, 0x01, 0x01, 0x11, 0x0E},
{0x06, 0x08, 0x10, 0x1E, 0x11, 0x11, 0x0E}, {0x1F, 0x01, 0x02, 0x04, 0x08, 0x08, 0x08},
{0x0E, 0x11, 0x11, 0x0E, 0x11, 0x11, 0x0E}, {0x0E, 0x11, 0x11, 0x0F, 0x01, 0x02, 0x0C},
}

A 5x7 font, A-Z then 0-9: seven rows of five bits, bit 4 the left pixel.

◆ glyphs

FAR u8 glyphs[36][16]
static

The glyphs as 2bpp tiles, built at boot from the bits above.

◆ layer

FAR u8 layer[(20 *8) *16]
static

The layer: 160 tiles of 16 bytes, composed here, sent to VRAM.

◆ layer_sum

u16 layer_sum

A checksum of the layer after each composition

◆ palette

const u8 palette[]
static
Initial value:
= {
0x00, 0x28,
0x00, 0x00,
0x00, 0x00,
0xFF, 0x7F,
}

◆ presses

u16 presses

A presses taken

◆ upload

u16 upload
static

Halves of the layer still to send (2 after a composition)

◆ x_off

u16 x_off

Pixels every line is shifted by (0-5): A steps it