Version 0.2.1b
oval() ovalfill() split() added
Commandline Arguments
-- Run Pico-8 from Terminal
pico-8 [switches] cart.p8

-splore			-- boot in splore mode

-width		n	-- set the window width 
-height		n	-- set the window height 
-windowed	n	-- set windowed mode off (0) or on (1)
-volume		n	-- set all audio volume [0..256]
-sound		n	-- set only sfx volume [0..256]
-music		n	-- set only music volume [0..256]
-joystick	n	-- joystick controls starts at player n (0..7)
-pixel_perfect	n	-- 1 for unfiltered screen stretching at integer scales
-preblit_scale	n	-- scale the display by n before blitting to screen
-draw_rect	x,y,w,h	-- absolute window coordinates and size to draw the p8 screen 
-run		cart	-- load and run a cartridge
-x		cart	-- execute a PICO-8 cart headless and then quit (experimental!)
-export		args	-- run EXPORT command in headless mode and exit
-p		args	-- pass a parameter string to the specified cartridge
-home_path	path	-- set the path to store config.txt and other user data files
-root_path	path	-- set the path to store cartridge files
-desktop	path	-- set a location for screenshots and gifs to be saved
-gif_scale	n	-- scale of gif captures. default: 2 (256x256 pixels)
-gif_len	n	-- set the maximum gif length in seconds (1..120)
-gui_theme	n	-- use 1 for a grey, higher contrast editor color scheme (0: blue)
-timeout	n	-- how many seconds to wait for splore downloads timeout (d: 30)
-software_blit	n	-- use software blitting mode off (0) or on (1)
-accept_future	n	-- use 1 to allow loading cartridges made w/ newer P8 versions
-screenshot_scale	n -- scale of screenshots.  default: 3 (368x368 pixels)
-foreground_sleep_ms	n -- how many milliseconds to sleep between frames.
-background_sleep_ms	n -- how many milliseconds to sleep between frames in bg
PICO-8 Specs
- display: 128x128, fixed 16 colour palette
- input: 6 buttons
- cartridge size: 32k
- sound: 4 channel, 64 definable chip blerps
- code: lua, max 8192 tokens of code
- sprites: single bank of 128 8x8 sprites + 128 shared
- map: 128x32 8-bit cels + 128x32 shared

Audio Manipulation
music([n, [fade_len, [channel_mask]]]) -- play music; n = -1: stop
sfx(n, [channel, [offset]]) -- play sfx; n = -1: stop in channel; n = -2: release loop in channel
Cart Data Manipulation
cartdata(id) -- permanent data storage in slot [id]; once/execution
dget(idx) -- get number at index
dset(idx, val) -- set number at index to value
Coroutines::view coroutines thread
cocreate(f) -- returns a coroutine that executes f
coresume(c) -- resume coroutine c execution
costatus(c) -- returns true if c is still executing, false otherwise
yield() -- use inside a coroutine; makes a coroutine pause execution until next resume

Execution Flow
_draw()		-- called once per visible frame
_init()		-- called once on program startup
_update()	-- called once per update at 30fps
_update60()	-- called once per update at 60fps
Flow Control
::label:: -- label
goto label -- jump

if (<condition>) -- inline if

if <condition> then
 -- if block
elseif <condition> then
 -- elseif block
 -- else block

while <condition> do
 -- while block

 -- repeat block
until <condition>

for <var> = <first>, <last>, <step> do
 -- for block

for <var> in all(<table>) do
 -- for block

for <key>, <value> in pairs(<table>) do
 -- for block

Graphics Manipulation
camera([x, y]) -- set camera position
circ(x, y, r, [col]) -- draw circle
circfill(x, y, r, [col]) -- draw filled circle
clip([x, y, w, h]) -- set screen clipping region
cls([col]) -- clear screen; col = clear color
color(col) -- set default color
cursor(x, y) -- set cursor and CR/LF margin position
fget(n, [f]) -- get values of sprite flags
fillp(mask) -- set fill pattern for circ, circfill, rect, rectfill, pset, and line
flip() -- flip screen back buffer (30fps)
fset(n, [f], v) -- set values of sprite flags
line(x0, y0, x1, y1, [col]) -- draw line
oval(x0, y0, x1, y1, [col]) -- draws an ellipse inside of a bounding rectangle
ovalfill(x0, y0, x1, y1, [col]) -- draws a colored ellipse
pal(c0, c1, [p]) -- swaps col 0 to col 1; p = 0 = draw palette; p = 1 = screen palette
palt(col, t) -- set transparency for colour to t (bool)
pget(x, y) -- get pixel colour
print(str, [x, y, [col]]) -- print string
pset(x, y, [col]) -- set pixel colour
rect(x0, y0, x1, y1, [col]) -- draw rectangle
rectfill(x0, y0, x1, y1, [col]) -- draw filled rectangle
sget(x, y) -- get spritesheet pixel colour
spr(n, x, y, [w, h], [flip_x], [flip_y]) -- draw sprite
sset(x, y, [col]) -- set spritesheet pixel colour
sspr(sx, sy, sw, sh, dx, dy, [dw, dh], [flip_x], [flip_y]) -- draw texture from spritesheet
 -- Draws a textured line between two points, sampling the map for data
tline(x0, y0, x1, y1, mx, my, [mdx], [mdy])
fillp() mask
|32768|16384| 8192| 4096|
| 2048| 1024| 512 | 256 |
| 128 |  64 |  32 |  16 |
|  8  |  4  |  2  |  1  |

Input Functions
btn([i, [p]]) -- get button i state for player p
btnp([i, [p]]) -- true when the button was not pressed the last frame; delays 4 frames after button held for 15 frames
Input::Custom Delays
-- Button check time delays; measured in frames @ 30FPS
-- The default values of 15 and 4 will be used if a value of 0 is given for delay
poke(0x5F5C, delay) -- sets the initial delay before repeating; 255 will turn off repeat completely
poke(0x5F5D, delay) -- sets the repeating delay.
Map Functions
map(cel_x, cel_y, sx, sy, cel_w, cel_h, [layer]) -- draw map; layers from flags; sprite 0 is empty
mget(x, y) -- get map value
mset(x, y, v) -- set map value
-- Functions just like map(), but is no longer used.
mapdraw(cel_x, cel_y, sx, sy, cel_w, cel_h, [layer])
Mathematical Functions
-- numeric representation range
-32768.0 .. 32767.99
abs(x) -- x absolute value atan2(x, y) -- coordinate to angle; range [0..1] cos(x) -- cosinus; range [0..1] flr(x) -- round down -flr(-x) -- not a function per se, but will work as ceil(x) max(x, y) -- x/y maximum mid(x, y, z) -- x/y/z middle value min(x, y) -- x/y minimum rnd(x) -- random; 0 <= n < x sgn(x) -- returns argument sign: -1 or 1; sgn(0) = 1 sin(x) -- x sine, [0..1]; inverted sqrt(x) -- x square root srand(x) -- set random seed
Memory Functions
-- The two following functions load from filename, and work with multi-cart export
-- copy bytes from ram to rom
cstore(dest_addr, src_addr, len, [filename])
-- copy bytes from rom to ram
reload(dest_addr, src_addr, len, [filename])

memcpy(dest_addr, src_addr, len) -- copy bytes
memset(dest_addr, val, len) -- set len bytes to val
peek(addr) -- read byte in ram address
poke(addr, val) -- write val in ram address
1. base ram (32kB)
2. cart rom
3. lua ram (1MB)
Memory::Ram Layout
0x0    -- gfx
0x1000 -- shared gfx2/map2
0x2000 -- map
0x3000 -- gfx flags
0x3100 -- song
0x3200 -- sfx
0x4300 -- user data
0x5e00 -- persistent cart data (256 bytes)
0x5f00 -- draw state
0x5f40 -- hardware state
0x5f80 -- gpio pins (128 bytes)
0x6000 -- screen (8k)
x & y   -- both bits are set
x | y   -- either bit is set
x ^^ y  -- either bit is set, but not both of them
~ x     -- each bit is not set
x << n  -- shift left n bits (zeros come in from the right)
x >> n  -- arithmetic right shift (the left-most bit state is duplicated)
x >>> n -- logical right shift (zeros comes in from the left)
x <<> n -- rotate all bits in x left by n places
x >>< n -- rotate all bits in x right by n places
band(x, y) -- both bits are set
bor(x, y)  -- either bit is set
bxor(x, y) -- either bit is set, but not both of them
bnot(x)    -- each bit is not set
shl(x, n)  -- shift left n bits (zeros come in from the right)
shr(x, n)  -- arithmetic right shift (the left-most bit state is duplicated)
lshr(x, n) -- logical right shift (zeros comes in from the left)
rotl(x, n) -- rotate all bits in x left by n places
rotr(x, n) -- rotate all bits in x right by n places
a = b -- set
a + b -- sum
a - b -- sub
a * b -- mul
a / b -- div
a \ b -- int div; ie: flr(x)/n
a % b -- mod
a ^ b -- pow
Operators::Augmented Assignment
a += b -- sum to
a -= b -- sub to
a *= b -- mul to
a /= b -- div to
a %= b -- mod to
a ^= b -- pow to
a == b -- equivalent
a ~= b -- non-equivalent
a != b -- non-equivalent
a > b  -- greater
a < b  -- less
a >= b -- greater or equivalent
a <= b -- less or equivalent
not a   -- negation
a and b -- conjunction
a or b  -- disjunction
Devkit Input Mode
poke(0x5f2d, 1) -- enable devkit input mode
stat(30) -- read keyboard had input (bool); repeats every 4 frames after key held for 15 frames
stat(31) -- read keyboard character
stat(32) -- read x coord
stat(33) -- read y coord
stat(34) -- read button bitmask; 1 = primary, 2 = secondary, 4 = middle
Extra Graphics Modes
poke(0x5f2c, 0) -- standard, 128x128
poke(0x5f2c, 1) -- horizontal stretch, 64x128
poke(0x5f2c, 2) -- vertical stretch, 128x64
poke(0x5f2c, 3) -- zoomed, 64x64
poke(0x5f2c, 4) -- standard, 128x128
poke(0x5f2c, 5) -- mirror left half
poke(0x5f2c, 6) -- mirror top half
poke(0x5f2c, 7) -- mirror top-left quarter
Raspberry Pi / Pocketchip GPIO
-- run pico-8 as root ("sudo pico-8")
-- 128 pin values in the range [0..255]
poke(0x5f80, value) -- send value to gpio0
peek(0x5f81) -- get value from gpio1
-- et cetera
Command Line Interface
assert(condition) -- verify that condition is true
cd .. -- change to parent directory
cd [dirname] -- change directory
dir() -- list items
exit() -- close pico-8 app
export(filename.html, [cart1.p8, cart2.p8 ... cart15]) -- export game in html; up to 15 extra carts (.p8 format)
export(filename.png) -- export spritesheet
export(filename.wav) -- export the current sfx / music
export(filename%d.wav) -- export all sfx as numbered files
extcmd(cmd) -- control screenshots; "label" = cart label; "screen" = screenshot; "rec" = start gif; "video" = save gif
folder() -- open carts folder in operating system
help() -- show summary of system commands
import(filename.png) -- import spritesheet. expects 128x128 png and colour-fits to the pico-8 palette
info() -- print cart info
install_demos() -- install demo p8 carts alongside pico-8 app
install_games() -- install selection of bbs carts
keyconfig() -- keyboard configuration for player buttons
load("@clip") -- paste cart from clipboard, bbs support
load(filename) -- load cart; works with multi-cart export
ls() -- list items
menuitem(index, [label, callback]) -- add an extra item to the pause menu; index in [1..5]; no label or callback removes the item
mkdir(dirname) -- create directory
printh(str, [filename, overwrite]) -- print str to terminal; append or overwrite to filename
reboot() -- reboot pico8
resume() -- resume cart execution
run() -- boot cart
save("@clip") -- copy cart to clipboard, bbs support
save(filename) -- save cart
shutdown() -- close pico-8 app
splore() -- explore cartridges
stat(x) -- read some execution values, read below
time() -- returns seconds since last reboot
type(v) -- returns type of v: number, string or table
-- After running the game with ctrl + r, press escape to pause execution
. -- Entering a '.' into the console will advance the game to the next frame
enter -- Continue entering the '.' character or simply press enter
print(player.x) -- Show the current, live x value of the player. Game does not cease execution, & updates each frame!
?player.x -- '?' functions just like 'print' and can be used in place as shorthand
resume() -- The 'resume' function will return the game to a normal running state.
pico8_gpio[] // read and write gpio pins
pico8_buttons[] // bitfields for player input
Private Functions
_get_frames_skipped() -- used automatically by _mainloop()
_get_menu_item_selected(n) -- returns true or false if the n-th menu item is selected; n in [1..5]; used automatically by _mainloop()
_mainloop() -- main pico-8's "while true"
_pausemenu[n].callback() -- execute the n-th menu item's callback; n in [1..5]; used automatically by _mainloop()
_set_mainloop_exists(n) -- ?
_update_buttons() -- used automatically by _mainloop()
holdframe() -- used automatically by _mainloop()

The stat() function returns information about the current runtime environment.
Each kind of information has an ID (a number), described below.

Stat Overview
stat(4) -- clipboard; after user pressed ctrl-v
stat([16..19]) -- index of playing sfx on channels [0..3]
stat([20..23]) -- note number (0..31) on channels [0..3]
stat(30) -- keyboard key hit; see "peek / poke" tab
stat(31) -- keyboard character; see "peek / poke" tab
stat(32) -- mouse x coord; see "peek / poke" tab
stat(33) -- mouse y coord; see "peek / poke" tab
stat(34) -- mouse button bitmask; see "peek / poke" tab
Stat::Memory and CPU
stat(0) --[[ Memory Usage
The number returned is a value in Kilobytes, with 1 representing 1024 bytes.
Any decimal value returned is accurate, for example, 1.875 is equivalent to 1920 bytes.

This value accounts for ANY & ALL data used in the Lua code, including variables and tables, etc.
Thus, the maxiumum amount this can return is 2048, ie, 2 Megabytes, the total amount of memory alloted to Lua.

This value does NOT include any peekable/pokeable RAM, ie, graphical/video, nor does it include the cart ROM.

stat(1) --[[ Total CPU Usage
Initializes at 0 from the first _update call after the most recent _draw call.
The value will increment steadily towards 1 as the next frame approaches.

Ultimately, if the _update function is used, a value of 1 would represent 1/30th of a second having elapsed.
If instead the _update60 function is used, a value of 1 would represent 1/60th of a second instead.

Any time this returns a value exceeding 1 is an indication that the current cart is beyond the processing power it
is allotted for that frame. This means that frames will likely be dropped to compensate for the slow down.

stat(2) --[[ System CPU Usage
This value represents the the range/behavior seen in stat(1)

The difference between the two is that this value will only increase when PICO-8 is processing unseen code.

For example, if the screen was cleared 70 times in a step, stat(2) would return a value > 1. 
That's because the cls() function is a system call, but if the frame was spent calculating PI,
stat(2) wouldn't rise, as such calculations are not system calls.

-- Single quotes are fastest. 
sonic = 'Movin around at the speed of sound.'
-- But you've still got the Prower to make that adverb feel faster in single quotes
tails = 'Can\'t stick around, gotta keep movin\' on.'

-- Double quotes can help avoid the backslashapostatrophe.
adventure = "Don't stop, believin."
-- But what if I want to include the next line of that non-copyrighted lyrical element in the same string?
newline = "\n"
-- A backslash before the letter 'n' will get that job done. There's a few more you can find here
getitout = "Don't stop, believin.\nDon't hold on to that feelin'."

-- But for the poets and commenters out there, the King of String, is the double parenthetical. 
-- What You See is What You Get; Anything within these brackets is interpreted as is, including new lines
"THROUGH me you pass into the city of woe:
Through me you pass into eternal pain:
Through me among the people lost for aye.
Justice the founder of my fabric mov'd:
To rear me was the task of power divine,
Supremest wisdom, and primeval love.
Before me things create were none, save things
Eternal, and eternal I endure.
"All hope abandon ye who enter here."
#	-- Retrieves the length of a string
..	-- Concatenation
sub(str, from, [to]) -- Get character[s] in the range [from]:[to]
Split a string into a table of elements delimited by the given separator (defaults to ",").
When convert_numbers is true, numerical tokens are stored as numbers (defaults to true).
Empty elements are stored as empty strings.
When the separator is "", every character is split into a separate element.
split(str, [separator], [convert_numbers])
	split("1,2,3") -- returns {1,2,3}
	split("one:two:3",":",false) -- returns {"one","two","3"}
	split("1,,2,") -- returns {1,"",2,""}

-- Convert val to a string; if hex is true and val is a number; Output: "0x0000.0000"
tostr(val, [hex])

-- Cast parseable str to number; nil if str isn't a number; "0xAF" format for hex
"123.45" + 0 -- alternative to tonum
chr(num) -- gets a string character from a value[0..255]
ord(str) -- gets the index [0..255] from a character
print(chr(135).. " : ".. ord('♥')) -- ♥ : 135 
String::Special Characters
print("l:\x8b r:\x91 u:\x94 d:\x83 o:\x8e x:\x97")
Table Functions
add(t, v) -- add v to t
all(t) -- used in 'for v in all(t)' loops
count(t) -- returns number of elements in the table
del(t, v) -- delete first instance of v in t
foreach(t, f) -- call f() for each v in t
ipairs(t) -- loops through a numerically indexed table; for _, v in ipairs(t) do end
pairs(t) -- loops through string indexed tables; for k,v in pairs(t) do end
pack(...) -- adds any number of arguments into a table and returns the table
unpack(t) -- returns all entries in a table as arguments
rnd(t) -- returns a random value from a table
Metatables::view metatables thread
mt = {} -- init metatable
setmetatable(t, mt) -- set metatable mt to table t
Metatables::Special Keys
-- object oriented programming; invoked as 't:foo()' / 't:bar()'
fun = {}
function dosomething() end
function dosomethingmore() end
mt.__index = fun

-- property assignment; invoked when calling 't[k] = v'
function mt.__newindex(t, k, v) rawset(t, k, v) end

-- weak references; keys and / or values
mt.__mode = "k" or "v" or "kv"

-- treat a table like a function; invoked when calling 't()'
function mt.__call(t) dosomething() end

-- hide metatable; returned by 'getmetatable(t)'
public_mt = {}
mt.__metatable = public_mt

-- string casting; returned by 'tostring(t)'
function mt.__tostring(t) return tostr(t) end

-- table length; returned by '#t'
function mt.__len(t) return #t end
Metatables::Mathematic Operators
-- unary minus; returned by '-t'
function mt.__unm(t) return -t end

-- addition; returned by 'a + b'
function mt.__add(a, b) return a + b end

-- subtraction; returned by 'a - b'
function mt.__sub(a, b) return a - b end

-- multiplication; returned by 'a * b'
function mt.__mul(a, b) return a * b end

-- division; returned by 'a / b'
function mt.__div(a, b) return a / b end

-- modulo; returned by 'a % b'
function mt.__mod(a, b) return a % b end

-- involution; returned by 'a ^ b'
function mt.__pow(a, b) return a ^ b end

-- concatenation; returned by 'a .. b'
function mt.__concat(a, b) return a .. b end
Metatables::Comparison Operators
-- check for equality; returned by 'a == b'
function mt.__eq(a, b) return a == b end

-- check for less-than; returned by 'a < b'
function mt.__lt(a, b) return a < b end

-- check for less-than-or-equal; returned by 'a <= b'
function mt.__le(a, b) return a <= b end
alt + enter / cmd + f
alt + f4 / cmd + q
reload and run:
ctrl + r
ctrl + s
cpu graph:
ctrl + p
mute / unmute:
ctrl + m
show fps:
ctrl + 1
ctrl + 6 / f6 / f1
cart img:
ctrl + 7 / f7 / f2
start video:
ctrl + 8 / f8 / f3
save video:
ctrl + 9 / f9 / f4
keyboard cursor:
navigate editors:
alt + right / alt + left
cli completion:
navigate lists:
left / right
navigate carts:
up / down / home / end / pageup / pagedown
launch cart:
x / o / menu
favourite cart:
Sprite / Map Editor
ctrl + z
copy (bbs support):
ctrl + c
paste (bbs support):
ctrl + v
space / mmb
navigate sprite l/r:
q / w
navigate sprite u/d:
shift + q / shift + w
navigate colours:
1 / 2
navigate tabs:
+ / -
shift + , / shift + .
flip y:
flip x:
Draw Tool
replace colour:
stamp tool
stamp w/ transparency:
select tool
select sprites:
shift + drag
shape tool
toggle shape:
leftclick on icon
fill shape:
Code Editor
skip across words:
ctrl + left / ctrl + right
jump to start of line:
ctrl + w
jump to end of line:
ctrl + e
select word:
double click
ctrl + x
ctrl + c
ctrl + v
ctrl + z
ctrl + y
toggle commenting:
ctrl + b
next code tab:
ctrl + tab
previous code tab:
ctrl + shift + tab
shift + tab
shift + enter
duplicate line:
ctrl + d
ctrl + f
search across tabs:
ctrl + h
repeat search:
ctrl + g
navigate functions:
alt + up / alt + down
start / end of code:
ctrl + up / ctrl + down
button glyphs:
shift + l, r, u, d, x, o
shift + qwetyipasfghjkzcvbnm
glyph mode:
ctrl + k
puny font mode:
ctrl + p
hiragana mode:
ctrl + j
katakana mode:
ctrl + k
SFX / Music Editor
play / pause:
ctrl + c
ctrl + v
set all notes:
shift + lmb
modify speed:
< / >
home, end, pageup, pagedown, mousewheel
navigate patterns:
+ / -
snap to Cm pentatonic:
speed x4:
release loop:
select all in note:
0 ::
1 ::
2 ::
3 ::
drop (drum kick!)
4 ::
fade in
5 ::
fade out
6 ::
fast arpeggio (4 notes)
7 ::
slow arpeggio (4 notes)