============================================================================================ PICO-8 v0.1.3 http://www.pico-8.com (c) Copyright 2014-2015 Lexaloffle Games LLP Author: Joseph White // hey@lexaloffle.com PICO-8 is built with: SDL2 http://www.libsdl.org Lua 5.2 http://www.lua.org // see license.txt GIFLIB http://giflib.sourceforge.net/ ============================================================================================ Welcome to PICO-8! PICO-8 is a fantasy console for making, sharing and playing tiny games and other computer programs. When you turn it on, the machine greets you with a shell for typing in Lua programs straight away and provides simple built-in tools for creating sprites, maps and sound. The harsh limitations of PICO-8 are carefully chosen to be fun to work with, encourage small but expressive designs and hopefully to give PICO-8 cartridges their own particular look and feel. :: Keys Toggle Fullscreen: Alt+Enter or command-F Quit: Alt+F4 or command-Q Reload/Run/Restart cart: Ctrl+R Quick-Save: Ctrl+S Player 1 keys: Cursors + ZX / NM Player 2 keys: SDFE + tab,Q / shift A :: Specs Display: 128x128, fixed 16 colour palette Input: 6 buttons x 2 players Cartridge size: 32k Sound: 4 channel, 64 definable chip blerps Code: Lua (max 15360 bytes of source code) Sprites: Single bank of 128 8x8 sprites (+128 shared) Map: Single 128x32 (+128x32 shared) :: Hello World After PICO-8 boots, try typing some of these commands followed by enter: PRINT("HELLO WORLD") RECTFILL(80,80,120,100,12) CIRCFILL(70,90,20,14) FOR I=1,4 DO PRINT(I) END (Note: PICO-8 only displays upper-case characters -- just type normally without capslock!) You can build up an interactive program by using commands like this in the code editing mode along with two special callback function _update and _draw. For example, the following program allows you to move a circle around with the cursor keys. Press escape to switch to the code editor and type or copy & paste the following code: X = 64 Y = 64 FUNCTION _UPDATE() IF (BTN(0)) THEN X=X-1 END IF (BTN(1)) THEN X=X+1 END IF (BTN(2)) THEN Y=Y-1 END IF (BTN(3)) THEN Y=Y+1 END END FUNCTION _DRAW() RECTFILL(0,0,127,127,5) CIRCFILL(X,Y,7,8) END Now press escape to return to the main console and type RUN to see it in action. See the example cartridges for more complex programs. :: Example Cartridges These cartridges are included with PICO-8 and can be installed by typing: INSTALL_DEMOS CD DEMOS API Demonstrates most PICO-8 functions JELPI Platform game demo w/ 2p support CAST 2.5D Raycaster demo MANDEL Mandelbrot explorer COLLIDE Example wall and actor collisions BUTTERFLY Serpinsky triangles thing DRIPPY Draw a drippy squiggle STOMPY Music cart WOO Music cart To run a cartridge, open PICO-8 and type: LOAD JELPI RUN Press escape to stop the program, and once more to enter editing mode :: Filesystem These commands can be used to manage files and directories (folders): DIR list the current directory CD BLAH change directory CD .. go up a directory CD / change back to top directory (on pico-8's virtual drive) MKDIR make a directory FOLDER open the current directory in the host operating system's file browser LOAD BLAH load a cart from the current directory SAVE BLAH save a cart to the current directory If you want to move files around, duplicate them or delete them, best use the FOLDER command and do it in the host operating system. The default location for PICO-8's drive is: Windows: C:/Users/Yourname/AppData/Roaming/pico-8/carts OSX: /Users/Yourname/Library/Application Support/pico-8/carts Linux: ~/.lexaloffle/pico-8/carts You can change this and other settings in pico-8/config.txt Tip: if you are a Dropbox user, it's possible to set the drive directory to be a shared dropbox folder in order to provide a single disk for PICO-8 machines spread across different host machines. :: Backups If you quit without saving changes, or overwrite an existing file, a backup of the cartridge is aved to pico-8/backup. :: Configuration :: config.txt You can find some settings in config.txt. Edit the file when PICO-8 is not running. Windows: C:/Users/Yourname/AppData/Roaming/pico-8/config.txt OSX: /Users/Yourname/Library/Application Support/pico-8/config.txt Linux: ~/.lexaloffle/pico-8/config.txt :: Commandline parameters pico-8 [switches] [filename.p8] -run boot filename.p8 on startup -width n set the window or screen width and adjust scale to fit if not specified -height n set the window or screen height and adjust scale to fit if not specified -scale n set the size of each PICO-8 pixel. "-scale 3" gives pixels rendered at 3x3 -windowed n set windowed mode off (0) or on (1) -sound n sound volume 0..256 -music n sound volume 0..256 -joystick n joystick controls starts at player n (0..7) :: Controller Setup PICO-8 uses the SDL2 controller configuration scheme. It will detect common controllers on startup and also looks for custom mappings in sdl_controllers.txt in the same directory as config.txt. sdl_controllers.txt has one mapping per line. To generate a custom mapping string for your controller, use either the controllermap program that comes with SDL2, or try http://www.generalarcade.com/gamepadtool/ :: Sharing Cartridges / HTML5 Exporter There are three ways to share carts: 1. Share the .p8 or .p8.png file directly with other PICO-8 users 2. Post the cart on the Lexaloffe BBS to get a web-playable version http://www.lexaloffle.com/pico-8.php?page=submit See save() for notes on how to generate .p8.png versions. (search for .png) 3. Export the cartridge to a stand-alone html5 version: EXPORT FOO.HTML This will generate two files: foo.html and foo.js (you need both!) You are free to distribute and use exported cartridges as you please, provided that you have permission from the author and contributors. The .html file is intended as a template that can be modified as needed. It includes some buttons to control settings and a link to an external website (PICO-8 BBS cartridges by default), along with javascript to block keypresses in order to prevent web page scrolling while the cartridge is played. Note that the width and height of the player can be configured, but should normally match the size of the canvas it is displayed on (580,540 by default). :: Screenshots, Videos and Cartridge Labels While a cartridge is running use: F6 Save a screenshot to desktop F7 Capture cartridge label image F8 Start recording a video F9 Save video to desktop (max: 8 seconds) // if F6..F9 are not available on your system, use F1..F4 Cartridge label is saved when using save() with p8.png format. You can save a video at any time (it is always recording) -- use F8 just to reset the video starting point if you want something less than 8 seconds long. :: Troubleshooting Common gotchas to watch out for: - Lua arrays are 1-based by default, not 0-based. FOREACH starts at T[1], not T[0]. - cos() and sin() take 0..1 instead of 0..PI*2, and sin() is inverted. - The bottom half of the spritesheet and bottom half of the map occupy the same memory. // Best use only one or the other if you're unsure how this works. - PICO-8 numbers only go up to 32767. - Toggle fullscreen: use alt-enter on OSX (command-F is used for searching text). ============================================================================================ Editor Modes ============================================================================================ Press escape to toggle between console and editor Click editing mode tabs at top right to switch or press ALT+LEFT/RIGHT ** WARNING: The second half of the sprite sheet (banks 2 and 3), and the bottom half of the map share the same cartridge space. It's up to you how you use the data, but be aware that drawing on the second half of the sprite sheet could clobber data on the map and vice versa. :: Code Editor Hold shift to select (or click and drag with mouse) CTRL-X, C, V to cut copy or paste selected CTRL-Z, Y to undo, redo CTRL-F, G to search for text, repeat search ALT-UP, DOWN to navigate to the previous, next function :: Sprite Editor The sprite editor is designed to be used both for sprite-wise editing and for freeform pixel-level editing. The sprite navigator at the bottom of the screen provides an 8x8-wise view into the sprite-sheet, but it is possible to use freeform tools (pan, select) when dealing with larger or oddly sized areas. Draw Tool Click and drag on the sprite to edit Applies to visible area Hold LCONTROL to search and replace a colour Use left moust button to select colour Stamp Tool Click to stamp whatever is in the Hold LCONTROL to stamp with transparency Select Tool // shortcut: LSHIFT or S Create a selection Enter or click to select none. If a pixel-wise selection is not present, many operations are instead applied to a sprite-wise selection. To select sprites, shift-drag in the sprite navigator. Pan Tool // shortcut: space View the spritesheet. Fill Tool Fill with the current colour Applies to the current selection If no selection, applies to visible area Extra keys CTRL-Z to undo // single step only in 0.2.0 CTRL-C to copy selected area or selected sprites CTRL-V to paste to current sprite location Q,W to switch to previous/next sprite 1,2 to switch to previous/next colour Tab to toggle fullscreen view Mousewheel to zoom (centered in fullscreen) Operations on selected area or selected sprites: f to flip v to flip vertically r to rotate (must be square selection) Cursor keys to move (loops if sprite selection) Sprite flags The 8 coloured circles are sprite flags for the current sprite. Each one can be true (on) or false (off), and are accessed by using the FSET and FGET functions. They are indexed from 0, from the left (0,1,2..7). See fset() for more information. :: Map Editor The pico-8 map is a 128x32 (or 128x64 using shared space) block of 8-bit values. Each value is shown in the editor as a reference to a sprite (0..255), but you can of course use the data to represent whatever you like. The tools are similar to the ones used in sprite editing mode. Select a sprite and click and drag to paint values into the map. To draw multiple sprites, select from sprite navigator with shift+drag To copy a block of values, use the selection tool and then stamp tool to paste To pan around the map, use the pan tool or hold space Q,W to switch to previous/next sprite :: Sfx Editor Click and drag current instrument Shift click an instrument to set all notes to that instrument Hold control while painting frequencies to snap to Cm pentatonic Click/right-click on SPD to decrease/increase speed (lower value means faster) // hold shift for x4 LP0 LP1 determines looping start and end points SPACE to start/stop a to release a looping sample Use the view mode buttons to edit the sfx's data as a graph or tracker-style. Tracker mode: each note shows: frequency octave instrument volume effect Shift-click instrument / effect / volume to set for all notes To enter a note, use q2w3er5t6y7ui zsxdcvgbhnjm (piano-like layout) New notes are given the selected instrument/effect values To delete a note, press backspace or set the volume to 0 (Setting volume to 0 can be used to delete a string of notes more easily) // note: from 0.1.2, non-qwerty keyboards use the same piano-like layout Effects: 0 none 1 slide 2 vibrato 3 drop 4 fade_in 5 fade_out 6 arp fast 7 arp slow Arpeggio commands (6,7) iterate over groups of 4 notes at speed 2 and 4 :: Music Editor Click/Right-click pattern numbers to indicate which sfx will be played for that pattern Top right: use loop start, loop back and stop flags to control playback flow. Space to start/stop ============================================================================================ Lua Syntax Primer ============================================================================================ PICO-8 programs are written using Lua syntax, but do not use the standard Lua library. The following is a brief summary of essential Lua syntax. For more details, or to find about proper Lua, see www.lua.org. :: Comments -- use two hyphens like this to ignore everything until the end of the line :: Types and assignment Types in Lua are numbers, strings, booleans and tables; NUM = 12/100 S = "THIS IS A STRING" B = FALSE T = {1,2,3} Numbers in pico-8 are all 16:16 fixed point. They range from -32768.0 to 32767.99 Hexidecimal notation with optional fractional parts can be used: 0x11 -- 17 0x11.4000 -- 17.25 :: Conditionals IF NOT B THEN PRINT("B IS FALSE") ELSE PRINT("B IS NOT FALSE") END IF (4 == 4) THEN PRINT("EQUAL") END IF (4 ~= 3) THEN PRINT("NOT EQUAL") END IF (4 <= 4) THEN PRINT("LESS THAN OR EQUAL") END IF (4 > 3) THEN PRINT("MORE THAN") END :: Loops FOR X=1,5 DO PRINT(X) END -- prints 1,2,3,4,5 X = 1 WHILE(X <= 5) DO PRINT(X) X = X + 1 END FOR X=1,10,3 DO PRINT(X) END -- 1,4,7,10 FOR X=5,1,-2 DO PRINT(X) END -- 5,3,1 :: Functions and Local Variables Y=0 FUNCTION PLUSONE(X) LOCAL Y = X+1 RETURN Y END PRINT(PLUSONE(2)) -- 3 PRINT(Y) -- 0 :: Tables In Lua, tables are a collection of key-value pairs where the key and value types can both be mixed. They can be used as arrays by indexing them with integers. A={} -- create an empty table A[1] = "BLAH" A[2] = 42 A["FOO"] = {1,2,3} -- Arrays use 1-based indexing by default A = {11,12,13,14} PRINT(A[2]) -- 12 -- The size of a table indexed with sequential 1-based integers: PRINT(#A) -- 4 -- Indexes that are strings can be written using dot notation PLAYER = {} PLAYER.X = 2 -- is equivalent to PLAYER["X"] PLAYER.Y = 3 -- see also the tables section in the api reference below. :: PICO-8 Shorthand PICO-8 also allows several non-standard, shorter ways to write common patterns. 1. IF THEN END statements on a single line can be expressed without the THEN & END IF (NOT B) I=1 J=2 -- is equivalent to: IF (NOT B) THEN I=1 J=2 END -- note that the condition must be surrounded by brackets. 2. unary math operators a += 2 -- equivalent to: a = a + 2 a -= 2 -- equivalent to: a = a - 2 a *= 2 -- equivalent to: a = a * 2 a /= 2 -- equivalent to: a = a / 2 a %= 2 -- equivalent to: a = a % 2 3. != operator Not shorthand, but pico-8 also accepts != instead of ~= for "not equal to" ============================================================================================ API ============================================================================================ PICO-8 is built on the Lua scripting language, but does not include the Lua standard library. Instead, a small api is offered in keeping with pico-8's minimal design and limited screen space. For an example program that uses most of the api functions, see /DEMOS/API.P8 Functions are written here as: function_name parameter [optional_parameter] System functions called from commandline can omit the usual brackets and string quotes: load blah.p8 --> load("blah.p8") -------------------------------------------------------------------------------------------------------- System -------------------------------------------------------------------------------------------------------- load filename save filename Load or save a cartridge Use ".png" format to save a png -- otherwise text format is used The ".p8" can be omitted in both cases, and it is automatically added save("blah") --> save("blah.p8") save("blah.png") --> save("blah.p8.png") load("blah.png") --> load("blah.p8.png") (if blah.png doesn't exist) Same goes for loading. If the file is not found, pico-8 will try again with ".p8" inserted. The ".png" can also be omitted, but only when loading load ("blah") --> tries "blah.p8.png" and then "blah.png" if "blah.p8" doesn't exist Once a cartridge has been loaded or saved, it can also be quick-saved with CTRL-S :: Saving .png carts with a text label and preview image To generate a preview image saved with the cart, run the program first and press F7 to grab whatever is on the screen. The first two lines of the program starting with '--' are also drawn to the cart's label. e.g. -- OCEAN DIVER LEGENDS -- BY LOOPY folder Open the carts folder in the host operating system. ls List all files in the current folder run Run from the start of the program Can be called from inside a program to reset program. resume Run from the existing cart state reboot Reboot the machine Useful for starting a new project stat x x:0 returns current memory useage (0..256) x:1 returns cpu useage for last frame (1.0 means 100% at 30fps) info Print out some information about the cartridge: code size, tokens, compressed size flip Flip the back buffer to screen and wait for next frame (30fps) Don't normally need to do this -- _draw() calls it for you. If your program does not call flip before a frame is up, and a _draw() callback is not in progress, the current contents of the back buffer are copied to screen. printh str Print a string to host operating system's console for debugging. -------------------------------------------------------------------------------------------- Program Structure -------------------------------------------------------------------------------------------- There are 3 special functions that, if defined by the user, are called during program execution: _update() Called once per update at 30fps _draw() Called once per visible frame _init() Called once on program startup _draw() is normally called at 30fps, but if it can not complete in time, pico-8 will attempt to run at 15ps and call _update() twice per visible frame to compensate. -------------------------------------------------------------------------------------------- Graphics -------------------------------------------------------------------------------------------- PICO-8 has a single bank of 128 8x8 sprites, plus another 128 that overlaps with the bottom half of the map data ("shared data"). These 256 sprites are collectively called the sprite sheet, and can be thought of as a 128x128 pixel image. All of PICO-8's drawing operations are subject to the current draw-state. The draw-state includes a camera position (for adding an offset to all coordinates), palette mapping (for recolouring sprites), clipping rectangle, and a draw colour that can optionally be set by any relevant function but otherwise persists. The draw state is reset each time a program is run. This is equivalent to calling: clip() camera() pal() color() Colours indexes: 0 black 1 dark_blue 2 dark_purple 3 dark_green 4 brown 5 dark_gray 6 light_gray 7 white 8 red 9 orange 10 yellow 11 green 12 blue 13 indigo 14 pink 15 peach clip [x y w h] Sets the screen's clipping region in pixels clip() to reset pget x y pset x y [c] Get or set the colour (c) of a pixel at x, y. sget x y sset x y [c] Get or set the colour (c) of a spritesheet pixel. fget n [f] fset n [f] v Get or set the value (v) of a sprite's flag f is the flag index 0..7 v is boolean and can be true or false The initial state of flags 0..7 are settable in the sprite editor, using the line of little colourful buttons. The meaning of sprite flags is up to the user, or can be used to indicate which group ('layer') of sprites should be drawn by map. If the flag index is omitted, all flags are retrieved/set as a bitfield fset(2, 1+2+8) -- sets bits 0,1 and 3 fset(2, 4, true) -- sets bit 4 print(fget(2)) -- 27 (1+2+8+16) print str [x y [col]] Print a string If only str is supplied, and the cursor reaches the end of the screen, a carriage return and vertical scroll is automatically applied. (terminal-like behaviour) cursor x y Set the cursor position and carriage return margin color col Set the default color to be used by drawing functions cls Clear the screen camera [x y] Set a screen offset of -x, -y for all drawing operations camera() to reset circ x y r [col] circfill x y r [col] Draw a circle or filled circle at x,y with radius r line x0 y0 x1 y1 [col] draw line rect x0 y0 x1 y1 [col] rectfill x0 y0 x1 y1 [col] Draw a rectange or filled rectange pal c0 c1 [p] Draw all instances of colour c0 as c1 in subsequent draw calls pal() to reset to system defaults (including transparency values) Two types of palette (p; defaults to 0) 0 draw palette : colours are remapped on draw // e.g. to re-colour sprites 1 screen palette : colours are remapped on display // e.g. for fades c0 colour index 0..15 c1 colour index to map to palt c t Set transparency for colour index to t (boolean) Transparency is observed by spr(), sspr() and map() e.g. palt(8, true) -- red pixels not drawn palt() resets to default: all colours opaque except colour 0 spr n x y [w h] [flip_x] [flip_y] draw sprite n (0..255) at position x,y width and height are 1,1 by default and specify how many sprites wide to blit. Colour 0 drawn as transparent by default (see palt()) flip_x=true to flip horizontally flip_y=true to flip vertically sspr sx sy sw sh dx dy [dw dh] [flip_x] [flip_y] Stretch rectangle from sprite sheet (sx, sy, sw, sh) // given in pixels and draw in rectangle (dx, dy, dw, dh) Colour 0 drawn as transparent by default (see palt()) dw, dh defaults to sw, sh flip_x=true to flip horizontally flip_y=true to flip vertically -------------------------------------------------------------------------------------------- Tables -------------------------------------------------------------------------------------------- add t v Add value v to the end of table t. Equivalent to t[#t+1] = v FOO={} -- create empty table ADD(FOO, 11) ADD(FOO, 22) PRINT(FOO[2]) -- 22 del t v Delete the first instance of value v in table t The remaining entries are shifted left one index to avoid holes. Note that v is the value of the item to be deleted, not the index into the table! del() can be called safely on a table's item while iterating over that table. A={1,10,2,11,3,12} FOR ITEM IN ALL(A) DO IF (ITEM < 10) THEN DEL(A, ITEM) END END FOREACH(A, PRINT) -- 10,11,12 PRINT(A[3]) -- 12 all t Used in FOR loops to iterate over all items in a table, in the order they were added. T = {11,12,13}; ADD(T,14) ADD(T,"HI") FOR V IN ALL(T) DO PRINT(V) END -- 11 12 13 14 HI PRINT(#T) -- 5 foreach t f For each item in table t, call function f with the item as a single parameter. FOREACH(T, PRINT) pairs t Used in FOR loops to iterate over table t, providing both the key and value for each item. Unlike all(), pairs() iterates over every item regardless of indexing scheme. Order is not guaranteed. T = {["HELLO"]=3, [10]="BLAH"} T.BLUE = 5; FOR K,V IN PAIRS(T) DO PRINT("K: "..K.." V:"..V) END Output: K: 10 v:BLAH K: HELLO v:3 K: BLUE v:5 -------------------------------------------------------------------------------------------- Input -------------------------------------------------------------------------------------------- btn [i [p]] get button i state for player p (default 0) i: 0..5: left right up down a_button b_button p: player index 0 or 1 If no parameters supplied, returns a bitfield of all 12 button states. // P0: bits 0..5 P1: bits 8..13 Default keyboard mappings to player buttons: player 0: cursors, Z,X / C,V / N,M player 1: ESDF, LSHIFT,A / TAB,Q,E btnp [i [p]] Same as btn() but only true when the button was not pressed the last frame btnp() also returns true every 4 frames after the button is held for 12 frames. Useful for things like 'press a button to continue' or menu item movement. -------------------------------------------------------------------------------------------- Audio -------------------------------------------------------------------------------------------- sfx n [channel [offset]] play sfx n on channel (0..3) from note offset (0..31) n -1 to stop sound on that channel n -2 to release sound on that channel from looping any music playing on the channel will be halted offset in notes (0..31) channel -1 (default) to automatically choose a channel that is not being used // this will never clobber music playback // if nothing plays, check you gave music() a channel_mask so that music // playback doesn't hog all channels. (e.g. 1+2 for the first channels) music [n [fade_len [channel_mask]]] play music starting from pattern n (0..63) n -1 to stop music fade_len in ms (default: 0) channel_mask specifies which channels to play music on e.g. to play on channels 0..2: 1+2+4 = 7 defaults to 15 -- all channels (1+2+4+8) -------------------------------------------------------------------------------------------------------- Map -------------------------------------------------------------------------------------------------------- mget x y mset x y v get or set map value (v) at x,y map cel_x cel_y sx sy cel_w cel_h [layer] draw section of map (in cels) at screen position sx, sy (pixels) if layer is specified, only cels with the same flag number set are drawn // Bitfield. So 0x5 means draw sprites with bit 0 and bit 2 set. // defaults to all sprites exception: sprite 0 is always taken to mean empty. e.g. map(0,0, 20,20, 4,2) -> draws a 4x2 blocks of cels starting from 0,0 in the map, to the screen at 20,20 -------------------------------------------------------------------------------------------------------- Memory -------------------------------------------------------------------------------------------------------- PICO-8 has 3 types of memory: 1. base ram (32k): see layout below. Access with peek() poke() memcpy() memset() 2. cart rom: same layout as base ram until 0x4300. Copy from cart to base ram with reload() 3. lua ram (256k): compiled program + variables. Pay no attention to the man behind the curtain. Technical note: // you probably don't need to know this While using the editor, the data being modified is in cart rom, but api functions such as spr() and sfx() only operate on base ram. PICO-8 automatically copies cart rom to base ram in two cases: 1. when a cartirdge is run() 2. when exiting any of the editor modes. :: Base ram memory layout 0x0 gfx 0x1000 gfx2/map2 (shared) 0x2000 map 0x3000 gfx_props 0x3100 song 0x3200 sfx 0x4300 user-defined 0x5f00 draw state (+ unused) 0x5f80 persistent cart data (64 bytes) 0x5fc0 unused 0x6000 screen (8k) Colour format (gfx/screen) is 2 pixels per byte: low bits on the left Map format is one byte per cel (normally used as a sprite index) peek addr poke addr val Read and write one byte to an address in base ram. Legal addresses are 0x0..0x7fff Reading or writing outside causes a fault memcpy dest_addr source_addr len Copy len bytes of base ram from source to dest Sections can be overlapping reload dest_addr source_addr len Same as memcpy, but copies from cart rom if source_addr >= 0x4300, can read code ascii into ram cstore dest_addr source_addr len Same as memcpy, but copies from base ram to cart rom cstore() is equivalent to cstore(0, 0, 0x4300) Can use for writing tools to construct carts or to visualize the state of the map / spritesheet using the map editor / gfx editor. if dest_addr >= 0x4300, can clobber program ascii on cart memset dest_addr val len Set len bytes to val (quite fast -- can use to draw unclipped horizonal scanlines etc) -------------------------------------------------------------------------------------------------------- Math -------------------------------------------------------------------------------------------------------- max x y min x y mid x y z Returns the maximum, minimum, or middle value of parameters For example, mid(7,5,10) returns 7 flr x Returns the closest integer below x flr(-0.3) returns -1.0 Same as (x%1) for positive values of x cos x sin x Returns the cosine of x, where 1.0 indicates a full circle sin is inverted to suit screenspace e.g. sin(0.25) returns -1 atan2 dx dy Converts dx, dy into an angle from 0..1 As with cos/sin, angle is taken to run anticlockwise in screenspace e.g. atan(1, -1) returns 0.125 sqrt x Return the square root abs x Returns the absolute (positive) value of x rnd x Returns a random number n, where 0 <= n < x If you want an integer, use flr(rnd(x)) srand x Sets the random number seed The seed is automatically randomized on cart startup Bitwise operations band x y bor x y bxor x y bnot x shl x y shr x y -------------------------------------------------------------------------------------------------------- Strings -------------------------------------------------------------------------------------------------------- s = "the quick brown fox" -- length print(#s) --> 19 -- joining strings print("three "..4) --> "three 4" -- sub() to grab substrings print(sub(s,5,9)) --> "quick" print(sub(s,5)) --> "quick brown fox" -------------------------------------------------------------------------------------------- Cartride Data -------------------------------------------------------------------------------------------- Each cartidge is able to store 64 numbers (256 bytes) of persistent data. This can be used for this things like high scores or to save player progress. cartdata id Call this once on cartridge load. id is a string up to 64 characters long, and should be unusual enough that other cartridges do not accidentally use the same id. e.g. cartdata("zep_jelpi") legal characters are a..z, 0..9 and underscore (_) returns true iff data was loaded. cartdata can not be called more than once per cartridge execution dget index Get the number stored at index (0..63) Use this only after you have called cartdata() dset index value Set the number stored at index (0..63) use this only after you have called cartdata() ------------------------------------------------------------------------------------------------------------ VERSION HISTORY ------------------------------------------------------------------------------------------------------------ v0.1.3 Added: paste into commandline Fixed: lua standard libraries accessible Fixed: command-line loading doesn't work Fixed: music pattern finished too early when all tracks set to looping Fixed: peek()ing odd bytes in sfx address space masks bit 7 Fixed: cstore and reload from code space should have no effect v0.1.2 Added: html5 cartridge exporter Added: Cartridge save data (64 fixed point numbers) Added: 8-player input Added: Demo carts: COLLIDE and BUTTERFLY Added: Command-line parameters // load cart, -run, settings Added: Alternative function keys (F6..F9 aliased as F1..F4) Added: pairs() Added: printh() for debugging Added: Tab completion for filenames in console Added: stack trace on runtime error Changed: music pattern length taken to be first non-looping channel's length Changed: noise instrument (6) has low frequency white noise scaled by volume Changed: screenshot captures whole window contents at display resolution Changed: del() moves remaining items up one index to maintain a packed table Changed: add(),del(),count(),all() no longer store extra fields Changed: removed count() from docs -- now just a legacy function. Use # operator instead. Changed: cursor only blinks while window is active Changed: peek(), poke() and binary operations (band()..) have no function call overhead Changed: yellow slightly warmer Changed: No camera snapping after pan in map mode Fixed: sqrt() crashing for 0 or >= 32761 Fixed: Semi-colon characters in text editor Fixed: Long lines split when saving in .p8 format Fixed: pget() does not respect camera position Fixed: Error message when peeking or poking outside of legal address space Fixed: Search replace colour fills one pixel outside of selected region Fixed: Playing an empty music pattern breaks subsequent music playback Fixed: Invalid sfx editing state on startup Fixed: Painting instruments values in frequency view also sets volumes Fixed: Inconsistent gif recording speeds Fixed: Unmapped joystick support Fixed: Compressed code size sometimes larger than uncompressed Fixed: mid() fails when first argument is not smallest Fixed: Scroll wheel changes sprite/map zoom while in code editor Fixed: CTRL-R (quick-run) drawing over current line in command mode Fixed: Label capture (F7) does not respect screen palette state Fixed: Syntax highlighting of api functions and hex numbers Fixed: Looping to 0 with negative step finishes at 1 Fixed: nil values printed as false instead of nil Fixed: Hexidecimal fractional parts Fixed: btnp() unresponsive when skipping frames Fixed: Editing mode is lost when using ctrl-r to run Fixed: Tracker note entry keys mapped, messing up piano-like layout Fixed: Shared gfx/map memory out of sync after some editor operations Fixed: Alt-gr character entry Fixed: Can map display palette to entries >= 16 using poke() Fixed: Using shift to select in code editor has wrong selection range Fixed: Dragging above top of text causes selection to flip to end Fixed: Duplicate at end of file listing v0.1.1 Added: Token-based code limiting (8192 tokens, 32k ascii text) Added: Freeform move, pan and selection in sprite and map editors Added: Flood-fill tool (sprite and map) Added: .GIF saver Added: CTRL-Stamp to stamp with transparency Added: Single-step undo for map and sprites Added: 2x2 brush Added: sqrt(), atan2() Added: CTRL-S to quick-save Added: CTRL-R reloads .p8 file and runs (useful for external text editing) Added: Automatic backups on overwriting or quitting without saving Added: Scroll wheel zooms in sprite editor Added: Customisable resolution // e.g. pico8 -width 580 Added: Strings highlighted as green Added: ALT-click can optionally simulate right click (see config.txt) Added: palt() to control transparency for spr(), sspr() Added: info() Changed: load() tries adding .p8.png, .png if file doesn't exist Changed: Draw operations apply only to selection when active Changed: Move operations (cursors) apply to selection if present Changed: Removed time() Changed: Random seed is random on cart startup Changed: api functions never read directly from cart rom Changed: sspr() can take negative values for dw, dh Fixed: Sparse table indexing with integers fails Fixed: Assignment operators and shortform if-then-else failing Fixed: sspr() failed when w0 == 128 Fixed: Circle drawing broken when camera not (0,0) Fixed: CPU hogging Fixed: Noise instrument clobbers rnd() sequence Fixed: Audio system not resetting on program reset Fixed: % operator sometimes wrong for negative values Fixed: Length operator (#) Fixed: Power operator (^) Fixed: Line clipping bug on right and bottom edges Fixed: print() precision for whole numbers Fixed: print() broken for negative y values Fixed: tokenization and keyword highlighting Fixed: sprite properties not copied/pasted Fixed: Only sfx 0..32 could be used as music patterns Fixed: Saving and loading a .p8 file adds newline to end of code Fixed: Drag selection to left margin in code editor -> selects all v0.1.0 Added: demo cart: hello.p8 (use install_demos) Added: CTRL-R from anywhere to run cart or restart cart Added: use a,s to select colour in gfx editor Added: black background behind Added: consistent operation cpu costs Added: btn(), btnp() with no arguments returns bitfield Added: fget(id) returns bitfield of that sprite's flags Changed: renamed mapdraw() to map() for consistency Changed: default sleep time is 5ms (better cpu consumption for laptops) Fixed: memory limiter Fixed: wonky line and circle drawing Fixed: shift-click volume in sfx editor to set all Fixed: number formatting is now never in scientific notation Fixed: clipped error messages in console Fixed: text undo stores rollback points when chaning line number Fixed: print(str) carriage returns to previous x v0.0.5 Added: help() Added: Ctrl+F / Ctrl+G to search for text, repeat search Added: del key in code editor Added: Short-hand single-line IF statements Added: Unary operators += -= /= *= %= Added: srand(), time(), added rnd() to docs Added: Ctrl+D to duplicate line Added: interactive ls() for multi-page file listings Added: band() bor() bxor() bnot() shl() shr() Added: runtime error line number Added: dir() (aliased to ls()) Changed: print() only autoscrolls when called with no parameters Changed: alt+up/down to skip between function definitions (was ctrl) Changed: sspr() dw, dh defaults to sw, sh Fixed: Load crashes on files that are not .p8 format or directories Fixed: Misc editor cursor position glitches Fixed: Crash when syntax error occurs before viewing code Fixed: Broken newlines after rebooting Fixed: mkdir() called with no parameters creating "(null)" directory Fixed: scrolling past top of code with scrollwheel Fixed: alt-f4 to fastquit v0.0.4 Added: Jelpi demo cart Added: Internal carts // use install_demos() Added: Joystick support Added: Undo/redo in code editor Added: Scroll wheel in code editor Added: LCTRL + UP/DOWN to navigate functions in code editor Added: LALT + LEFT/RIGHT to switch editing modes Added: btnp() Added: Release looping sample (a in editor , sfx(-2, channel) in code) Changed: Music stops when pausing program execution Changed: Allow 8 settable sprite flags Changed: Made noise instrument more bassy Fixed: Home, end keys Fixed: Sprite flags 4,5 not saved Fixed: mset() discarding 4 high bits Fixed: Crash when highlighting long strings v0.0.3 Added: Palette mapping type 1 (on display) Added: Collections can be initialized with c={1,2,..} Added: holdframe() // used automatically by _draw(), update() Added: Sprite selections and operations across selections Added: Map selection and stamp tool Added: Immediate mode screen buffer preserved while switching views Added: Channel mask for music playback Added: Memory mapping for live sound data Added: .png cart format Added: Sprite navigation by keyboard (-, +) Fixed: Strict 4-channel sound Fixed: Automatic sfx channel selection (channel index: -1) v0.0.2 Added: Command history Added: P2 keys Added: Boot sequence Added: Windows, 64-bit linux builds Added: CPU cost of internal api functions Added: Separate song channel index and mute status Added: Memory mapping Added: Search/replace colour in sprite editor Added: Copy/paste sprites and map regions Improved: Immediate mode command editing Improved: Editor cursor behaviour Fixed: Automatic audio channel selection v0.0.1 First Alpha