PICO-8 Wiki
No edit summary
Tag: Source edit
No edit summary
Tag: Source edit
Line 228: Line 228:
   
   
== Custom font ==
+
== Custom fonts ==
   
 
PICO-8 supports a single custom font in addition to its default font. Your program must load the font data starting at RAM address 0x5600, including a header that describes attributes of the font. With this font in memory, you enable the font with the control character <code>\014</code>. Subsequent characters are printed in the custom font. To return printing to the default font, print code <code>\015</code>. As with other effects, printing returns to the default font at the end of the [[Print|print()]].
 
PICO-8 supports a single custom font in addition to its default font. Your program must load the font data starting at RAM address 0x5600, including a header that describes attributes of the font. With this font in memory, you enable the font with the control character <code>\014</code>. Subsequent characters are printed in the custom font. To return printing to the default font, print code <code>\015</code>. As with other effects, printing returns to the default font at the end of the [[Print|print()]].

Revision as of 21:28, 31 August 2021

The P8SCII character set includes 16 control codes that produce effects when printed to the screen. These are typically invoked using escape sequences in string literals, as shown below. They can also be printed by code number via chr().

Some control codes accept arguments as characters printed immediately after the control code. In some cases, an argument is a single character that represents a numeric value. This character is typically a digit 0-9 (values 0-9) or a letter a-z (values 10-36). For attributes that accept larger values (such as audio settings), values above 36 can be entered with any P8SCII character above the higher z: { is 37, | is 38, 🐱 is 44, and so on.

Control code parameters are noted below, as in the official documentation, as P0 and P1.

Positioning text

Several control codes adjust the cursor position when printed. Subsequent printing continues from the new cursor position.

These codes replicate the corresponding behavior of an ASCII terminal:

  • \b : Backspace. Moves the cursor one character width (4 pixels) to the left. This does not erase any characters from the screen.
  • \t : Tab. Advances the cursor to the next tab stop to the right. By default, tab stops are four characters (16 pixels) wide.
  • \n : Newline. Advances the cursor to the next line and returns it to the current left margin (either 0 or whatever was last set by cursor()). If the cursor is at the bottom of the screen, this scrolls the screen up, similar to a teletype.
  • \r : Carriage return. Returns the cursor to the current left margin without advancing to the next line.

When printed to a terminal using printh(), these codes behave as their ASCII counterparts. These are the only control codes that do this in a terminal.

print("initials\tscore")
print("aaa\t\t100000")
print("bbb\t\t090000")
print("ccc\t\t080000")

Tip: You can adjust PICO-8's tab stop width with a special command character code. See \^s below.

Three control codes can shift the cursor by a number of pixels:

  • \- P0 : horizontal offset
  • \| P0 : vertical offset
  • \+ P0 P1 : horizontal and vertical offsets

The value 16 is subtracted from these parameters, allowing for an actual range of offsets from -16 to +19.

-- offset each word by +4 pixels vertically ("j" = 20, 20 - 16 = +4)
print("my \|jawesome \|jgame")


Changing text colors

Two control codes change the text color:

  • \f P0 : foreground color
  • \# P0 : background color

Each code takes one parameter, a hexadecimal character corresponding to the PICO-8 color value.

print("\f6hello \f3goodbye")

print("\f7my \f5\#9awesome\f7\#0 game")

The background color is reset to transparent at the end of the print() function. The foreground color is not reset. Changing the foreground color with a control code is similar to changing the pen color with color() or any of the drawing commands (such as print()'s color argument).

Note: Color control codes do not follow the palette settings of the draw state for draw operations, as set by pal() pal(..., 0) and palt(). They do honor full-screen palette swaps via pal(..., 1).


Special commands

The special command control code can perform visual effects based on arguments. The first code is \^, followed by a command character and any arguments expected by that command.

Skipping frames (pausing)

\^1 through \^9 skips a number of frames before continuing printing. The number of frames to skip corresponds to the number: 1, 2, 4, 8, 16, 32, 64, 128, or 256 frames, respectively.

print("3...\^6 2...\^6 1...\^6 blastoff!")

All program execution stops while print() waits for the frames. _update() and _draw() are not called for these frames.

function _update() end
function _draw()
 cls()
 print("🐱", rnd(120), rnd(120), rnd(16))
 print("3...\^6 2...\^6 1...\^6", 0, 0, 7)
emd

Clearing the screen

\^c P0 clears the screen with a given background color. It also resets the cursor position to (0, 0).

print("\^c3\f7it's a new day!")

Homing the cursor

When you call print(), the starting position of the cursor is considered the "home" position. \^g returns the cursor to its home position.

print("\n\ndown here\^gno up here!")

\^h updates the home position to be the cursor's current position.

print("\n\ndown here\n\^h\n\n\nfurther down\^gand i end up here!")

Moving the cursor to an absolute position

\^j P0 P1 sets the cursor to an absolute (x, y) pixel position. Each parameter value is multiplied by 4.

-- coordinates x=40 ("a" = 10, 10 * 4 = 40), y=48 ("c" = 12, 12 * 4 = 48)
print("\^jacgame over")

Setting the tab stop width

By default, the tab stop width is 16 pixels, equivalent to four 4-wide characters. You can change the tab stop width using the \^s P0 special command. The argument is the tab stop width in pixels.

print("\^samonth\tdeposit\tbalance")
print("\^sa1\t500\t500")
print("\^sa2\t250\t750")
print("\^sa3\t325\t1075")

Note: As with most control code effects, the tab stop width resets to 16 pixels at the end of the print() call.

Setting the character size (cursor advance rate)

\^x P0 and \^y P0 set the effective width and height of each character for the purposes of advancing the cursor. The parameter is the number of pixels.

By default, the width and height are that of a standard character: 4 x 6. Increasing the sizes causes letters to print farther apart. Decreasing the sizes causes them to print closer together or overlapping.

When a wide character (128 and above) is printed, the width is increased by 4 just for that character. This is true regardless of the width setting.

print("\^x6\^yathe curse\nof the\nstriped c🐱t")

Changing character rendering modes

The following special commands describe modes that change how characters are rendered. Each mode is either on or off. To enable, use the special command: \^i To disable, use - before the command: \^-i

  • \^w : Wide. Doubles the width.
  • \^t : Tall. Doubles the height.
  • \^. : Dotty. When wide or tall, only even pixels are rendered.
  • \^p : Pinball. Equivalent to wide, tall, and dotty.
  • \^i : Inverted. The foreground color is used as the background, and vice versa.
  • \^b : Bordered. Text has left and top padding. (On by default.)
  • \^# : Solid background. The default is a transparent background.

Modes can be combined: \^w\^t renders wide and tall characters.


Audio commands

The \a control code triggers sound effects during printing. Unlike other control codes, \a can be followed by any number of characters describing the sound effects to play. To end the sequence, use a space. This space character is not printed.

To produce a simple beep, use \a without arguments:

print("\a alert: something happened")

To play a sound effect, provide the SFX number in decimal as the sole argument:

print("\a13 alert: something wild happened")

You can describe an entire sound effect with a string of parameters to the audio command, including notes, instruments, effects, and more. This overwrites one of the SFX slots before playing the sound. If you provide an SFX number followed by a string, it will be written to that SFX slot. (It is written to RAM, not to the cart itself, and will not appear in the SFX editor.) If you do not specify an SFX number, PICO-8 will attempt to choose an unused slot between 60 and 63.

Two sound effect parameters are set at the beginning of the string, because they apply to the full effect:

  • s P0: the sfx speed
  • l P0 P1: loop start and end points

The rest of the string describes up to 32 notes, with optional codes to change the instrument, volume, and effect used for subsequent notes.

A note is a letter between a and g, followed by an optional # (sharp) or - (flat), and an optional octave number between 1 and 4.

print "\ace-g"   -- minor triad

To change settings for subsequent notes:

  • i P0: The instrument. The default is 5.
  • v P0: The volume. The default is 5.
  • x P0: The effect. The default is 0 (no effect).
  • < or >: Decrease or increase the previously set volume by one.

For example, to play a fast (speed 4), staccato (effect 5) arpeggio starting at C1:

print "\as4x5c1egc2egc3egc4"

Tip: Like all PICO-8 sound and music, sounds play in the background while printing continues. You can use the frame skipping special command to add delays to printing to wait for sound effects, like so:

print("you win!\as4x5c1egc2egc3egc4 \^4\ncongratulations!")


Decoration characters

The control character \v can be used to decorate the last printed character with another character at a given offset, without needing to otherwise manage the cursor position. After the decorating character is printed, the previous cursor position is restored.

The format is \v P0 char, where P0 is a number giving the desired offset, and char is any character to print at that offset (relative to the previous printed character).

The offset has x packed into the lowest 2 bits, and starts (-2,-8) in reading order. So 3 means (+1, -8), 4 means (-2, -7) and so on.

For example, to write "café!", using a comma to draw the accute accent:

print"\ncafe\vb,!"

In this case P0 is 'b', which is read as the number 11. So the comma is drawn at:

x = (11%4)-2 = 1
y = (11\4)-8 = -6


Custom fonts

PICO-8 supports a single custom font in addition to its default font. Your program must load the font data starting at RAM address 0x5600, including a header that describes attributes of the font. With this font in memory, you enable the font with the control character \014. Subsequent characters are printed in the custom font. To return printing to the default font, print code \015. As with other effects, printing returns to the default font at the end of the print().

Tip: Drawing and storing font data in code can be challenging, so there's a tool to make this easier. Type load #font_snippet to load this tool into PICO-8. The font snippet tool lets you draw your font in the sprite editor, then export it as a single compact poke() statement that loads the entire font into memory. Paste this code snippet into your cart, then use the control codes to activate it.

Font memory

The custom font memory layout consists of 8 bytes per character for all 256 characters in the P8SCII character set, for a total of 2048 bytes. Each character is an 8 x 8 bitfield. Bits are drawn left to right starting with the least significant bit. For examples:

  0x01    #_______
  0x15    #_#_#___
  0x80    _______#
  0xfe    _#######

Character 0 is never printed, so its bytes (starting at address 0x5600) are used as the header for the font.

  • 0x5600: Character width in pixels. Can be more than 8, but only 8 pixels are drawn. The print cursor advances horizontally by this amount for each character.
  • 0x5601: Character width for character 128 and above.
  • 0x5602: Character height in pixels. The print cursor advances vertically by this amount for each newline.
  • 0x5603: Draw offset x, in pixels. This is an offset from the cursor position where the character is drawn. The new cursor position does not include this offset.
  • 0x5604: Draw offset y, in pixels.

The following simple example defines a custom font of size 8 x 8 with no draw offset, redefines character #16 (address 0x5680-0x5687) as a triangle shape, prints the \014 control code to switch to the custom font, then prints three #16 characters (\016). It then disables the custom font (\015) to print a word in the default font.

poke(0x5600, 8)    -- char width
poke(0x5601, 8)    -- char width for high cars
poke(0x5602, 8)    -- char height
poke(0x5603, 0)    -- draw x offset
poke(0x5604, 0)    -- draw y offset

poke(0x5680, 1)    -- #_______
poke(0x5681, 3)    -- ##______
poke(0x5682, 7)    -- ###_____
poke(0x5683, 15)   -- ####____
poke(0x5684, 31)   -- #####___
poke(0x5685, 63)   -- ######__
poke(0x5686, 127)  -- #######_
poke(0x5687, 255)  -- ########

cls()
print("\014\016\016\016\015 tada\n\n")

Note: While there is memory space in font memory for defining glyphs for P8SCII codes 0-15, these codes are reserved for the P8SCII control codes. Printing these codes will have their control code effects and never print the glyphs.


Terminating printing

When print() encounters the \0 control code, it stops printing.

print("sorry you're breaking up i'm going into a tun\0nel")

Note: Without coordinates, print() normally prints a newline at the end of the string. When the string contains the null terminator code, print() will not print the newline.


Repeating characters

The \* control code takes a numeric argument and repeats the next character that many times.

print("\*3a")   -- prints "aaa"


Default attributes

Control codes modify printing attributes during the printing of a string. When print() completes, it resets these attributes back to their default settings. (As noted above, cursor position and foreground color are exceptions: these are properties of the draw state.)

You can modify the default settings of these attributes so that every print() starts with these settings. To modify the settings, poke() new values into memory addresses 0x5f58 through 0x5f5b.

Default rendering modes

Address 0x5f58 is a bitfield for the character rendering modes. Bit 0x1 enables the rendering modes, and must be set to 1 for any of the modes to take effect. These modes are:

  • 0x1: Enable
  • 0x2: Padding
  • 0x4: Wide
  • 0x8: Tall
  • 0x10: Solid background
  • 0x20: Invert
  • 0x40: Dotty
  • 0x80: Use custom font

For example, to enable "pinball" text by default for all printing:

-- set enable, padding, wide, tall, inverted, dotty
poke(0x5f58, 0x1 | 0x2 | 0x4 | 0x8 | 0x20 | 0x40)

print("on sale now!")
print("how do i turn this off?")

-- clear all flags, including enable
poke(0x5f58, 0)

print("phew!")

Default sizes and offsets

Defaults for character sizes (cursor travel), the tab width, and the draw offsets can be changed with addresses 0x5f59 through 0x5f5b.

Each value is 4 bits wide (a "nibble"), and occupies either the low nibble (0x8, 0x4, 0x2, 0x1) or the high nibble (0x80, 0x40, 0x20, 0x10). The value is stored most significant bit first.

  • 0x5f59 low nibble: Character width
  • 0x5f59 high nibble: Character height
  • 0x5f5a low nibble: Character width for codes above 128
  • 0x5f5a high nibble: Tab stop width, in increments of 4 pixels (4-64)
  • 0x5f5b low nibble: Draw offset x, in pixels
  • 0x5f5b high nibble: Draw offset y, in pixels
-- set default draw offset to y of 3 pixels, x of 2 pixels
poke(0x5f5b, 0x32)
print("shifted\n\n")

-- update the draw offset of y to 1 pixel, keeping x at the previous setting
poke(0x5f5b, 0x10 | (peek(0x5f5b) & 0x0f))
print("shifted\n\n")