4371 lines
199 KiB
Plaintext
4371 lines
199 KiB
Plaintext
![]() |
====================================================================================================
|
||
|
PICO-8 User Manual
|
||
|
====================================================================================================
|
||
|
|
||
|
PICO-8 v0.2.5g
|
||
|
https://www.pico-8.com
|
||
|
(c) Copyright 2014-2023 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
|
||
|
ws281x by jgarff // see license.txt
|
||
|
GIFLIB http://giflib.sourceforge.net/
|
||
|
WiringPi http://wiringpi.com/
|
||
|
libb64 by Chris Venter
|
||
|
miniz by Rich Geldreich
|
||
|
z8lua by Sam Hocevar https://github.com/samhocevar/z8lua
|
||
|
|
||
|
Latest version of this manual (as html, txt) and other resources:
|
||
|
|
||
|
https://www.lexaloffle.com/pico-8.php?page=resources
|
||
|
|
||
|
:: 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
|
||
|
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.
|
||
|
|
||
|
:: Specifications
|
||
|
|
||
|
Display: 128x128, fixed 16 colour palette
|
||
|
Input: 6-button controllers
|
||
|
Carts: 32k data encoded as png files
|
||
|
Sound: 4 channel, 64 definable chip blerps
|
||
|
Code: P8 Lua (max 8192 tokens of code)
|
||
|
CPU: 4M vm insts/sec
|
||
|
Sprites: Single bank of 128 8x8 sprites (+128 shared)
|
||
|
Map: 128 x 32 Tilemap (+ 128 x 32 shared)
|
||
|
|
||
|
====================================================================================================
|
||
|
Getting Started
|
||
|
====================================================================================================
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
Keys
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
ALT+ENTER: Toggle Fullscreen
|
||
|
ALT+F4: Fast Quit (Windows)
|
||
|
CTRL-Q: Fast Quit (Mac, Linux)
|
||
|
CTRL-R: Reload / Run / Restart cartridge
|
||
|
CTRL-S: Quick-Save working cartridge
|
||
|
CTRL-M: Mute / Unmute Sound
|
||
|
ENTER / P: Pause Menu (while running cart)
|
||
|
|
||
|
Player 1 default keys: Cursors + ZX / NM / CV
|
||
|
Player 2 default keys: SDFE + tab,Q / shift A
|
||
|
|
||
|
To change the default keys use the KEYCONFIG utility from inside PICO-8:
|
||
|
|
||
|
> KEYCONFIG
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
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 functions @_UPDATE and @_DRAW. For example, the following
|
||
|
program allows you to move a circle around with the cursor keys. Press Esc 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()
|
||
|
CLS(5)
|
||
|
CIRCFILL(X,Y,7,14)
|
||
|
END
|
||
|
|
||
|
Now press Esc to return to the console and type RUN (or press CTRL-R) to see it in action.
|
||
|
Please refer to the demo cartridges for more complex programs (type INSTALL_DEMOS).
|
||
|
|
||
|
If you want to store your program for later, use the SAVE command:
|
||
|
|
||
|
> SAVE PINKCIRC
|
||
|
|
||
|
And to load it again:
|
||
|
|
||
|
> LOAD PINKCIRC
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
Example Cartridges
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
These cartridges are included with PICO-8 and can be installed by typing:
|
||
|
|
||
|
> INSTALL_DEMOS
|
||
|
> CD DEMOS
|
||
|
> LS
|
||
|
|
||
|
HELLO Greetings from PICO-8
|
||
|
API Demonstrates most PICO-8 functions
|
||
|
JELPI Platform game demo w/ 2p support
|
||
|
CAST 2.5D Raycaster demo
|
||
|
DRIPPY Draw a drippy squiggle
|
||
|
WANDER Simple walking simulator
|
||
|
COLLIDE Example wall and actor collisions
|
||
|
|
||
|
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.
|
||
|
|
||
|
A small collection of BBS carts can also be installed to /GAMES with:
|
||
|
|
||
|
> INSTALL_GAMES
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
File System
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
These commands can be used to manage files and directories (folders):
|
||
|
|
||
|
LS 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 BLAH 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, 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: The drive directory can be mapped to a cloud drive (provided by Dropbox, Google Drive or
|
||
|
similar) in order to create a single disk shared between PICO-8 machines spread across
|
||
|
different host machines.
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
Loading and Saving
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
When using LOAD and SAVE, the .P8 extension can be omitted and is added automatically.
|
||
|
|
||
|
> SAVE FOO
|
||
|
SAVED FOO.P8
|
||
|
|
||
|
Cartridge files can also be dragged and dropped into PICO-8's window to load them.
|
||
|
|
||
|
Using .p8.png filename extension will write the cartridge in a special image format that looks
|
||
|
like a cartridge. Using .p8.rom" writes in a raw 32k binary format.
|
||
|
|
||
|
Use a filename of "@clip" to load or save to the clipboard.
|
||
|
|
||
|
Use a filename of "@url" to save to clipboard as a pico-8-edu.com url if it can be encoded in
|
||
|
2040 characters (code and gfx only).
|
||
|
|
||
|
Once a cartridge has been loaded or saved, it can also be quick-saved with CTRL-S
|
||
|
|
||
|
:: Saving .p8.png carts with a text label and preview image
|
||
|
|
||
|
To generate a label image saved with the cart, run the program first and press CTRL-7 to
|
||
|
grab whatever is on the screen. The first two lines of the program starting with '--' are
|
||
|
also drawn to the cart's label.
|
||
|
|
||
|
-- OCEAN DIVER LEGENDS
|
||
|
-- BY LOOPY
|
||
|
|
||
|
:: Code size restrictions for .p8.png / .p8.rom formats
|
||
|
|
||
|
When saving in .png or .rom format, the compressed size of the code must be less than 15360
|
||
|
bytes so that the total data is <= 32k.
|
||
|
|
||
|
To find out the current size of your code, use the INFO command. The compressed size limit
|
||
|
is not enforced for saving in .p8 format.
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
Using an External Text Editor
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
It is possible to edit .p8 files directly with a separate text editor. Using CTRL-R to run a
|
||
|
cartridge will automatically re-load the file if:
|
||
|
|
||
|
1. There are no unsaved changes in the PICO-8 editors, AND<br> 2. The file differs in
|
||
|
content from the last loaded version.
|
||
|
|
||
|
If there are changes to both the cart on disk and in the editor, a notification is displayed:
|
||
|
|
||
|
DIDN'T RELOAD; UNSAVED CHANGES
|
||
|
|
||
|
Alternatively, .lua text files can be modified in a separate editor and then included into the
|
||
|
cartridge's code each time it is run using @{#INCLUDE} (in the desired code location):
|
||
|
|
||
|
#INCLUDE YOURFILE.LUA
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
Backups
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
When quitting without saving changes, or overwriting an existing file, a backup of the
|
||
|
cartridge is saved to {appdata}/pico-8/backup. An extra copy of the current cartridge can also
|
||
|
be saved to the same folder by typing BACKUP.
|
||
|
|
||
|
To open the backups folder in the host operating system's file browser, use:
|
||
|
|
||
|
> FOLDER BACKUPS
|
||
|
|
||
|
It is then possible to drag and drop files into the PICO-8 window to load them.
|
||
|
|
||
|
From 0.2.4c, periodic backups are also saved every 20 minutes when not idle in the editor,
|
||
|
which means the backups folder will grow by about 1MB every 5 hours. This can be disabled or
|
||
|
adjusted in config.txt
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
Configuration
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
PICO-8 reads configuration settings from config.txt at the start of each session, and saves
|
||
|
it on exit (so you should edit config.txt when PICO-8 is not running).
|
||
|
|
||
|
The location of the config.txt file depends on the host operating system:
|
||
|
|
||
|
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
|
||
|
|
||
|
Use the -home switch (below) to use a different path to store config.txt and other data.
|
||
|
|
||
|
Some settings can be changed while running PICO-8 by typing CONFIG SETTING VALUE. (type
|
||
|
CONFIG by itself for a list)
|
||
|
|
||
|
:: Commandline parameters
|
||
|
|
||
|
// note: these override settings found in config.txt
|
||
|
|
||
|
pico8 [switches] [filename.p8]
|
||
|
|
||
|
-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 audio volume 0..256
|
||
|
-joystick n joystick controls starts at player n (0..7)
|
||
|
-pixel_perfect n 1 for unfiltered screen stretching at integer scales (on by default)
|
||
|
-preblit_scale n scale the display by n before blitting to screen (useful with -pixel_perfect 0)
|
||
|
-draw_rect x,y,w,h absolute window coordinates and size to draw pico-8's screen
|
||
|
-run filename load and run a cartridge
|
||
|
-x filename execute a PICO-8 cart headless and then quit (experimental!)
|
||
|
-export param_str run EXPORT command in headless mode and exit (see notes under export)
|
||
|
-p param_str pass a parameter string to the specified cartridge
|
||
|
-splore boot in splore mode
|
||
|
-home 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
|
||
|
-screenshot_scale n scale of screenshots. default: 3 (368x368 pixels)
|
||
|
-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 higher contrast editor colour scheme
|
||
|
-timeout n how many seconds to wait before downloads timeout (default: 30)
|
||
|
-software_blit n use software blitting mode off (0) or on (1)
|
||
|
-foreground_sleep_ms n how many milliseconds to sleep between frames.
|
||
|
-background_sleep_ms n how many milliseconds to sleep between frames when running in background
|
||
|
-accept_future n 1 to allow loading cartridges made with future versions of PICO-8
|
||
|
-global_api n 1 to leave api functions in global scope (useful for debugging)
|
||
|
|
||
|
:: 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/
|
||
|
|
||
|
To find out the id of your controller as it is detected by SDL2, search for "joysticks" or
|
||
|
"Mapping" in log.txt after running PICO-8. This id may vary under different operating systems.
|
||
|
See: https://www.lexaloffle.com/bbs/?tid=32130
|
||
|
|
||
|
To set up which keyboard keys trigger joystick buttons presses, use KEYCONFIG.
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
Screenshots and GIFS
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
While a cartridge is running use:
|
||
|
|
||
|
CTRL-6 Save a screenshot to desktop
|
||
|
CTRL-7 Capture cartridge label image
|
||
|
CTRL-8 Start recording a video
|
||
|
CTRL-9 Save GIF video to desktop (8 seconds by default)
|
||
|
|
||
|
You can save a video at any time (it is always recording); CTRL-8 simply resets the video
|
||
|
starting point. To record more than 8 seconds, use the CONFIG command (maximum: 120)
|
||
|
|
||
|
CONFIG GIF_LEN 60
|
||
|
|
||
|
If you would like the recording to reset every time (to create a non-overlapping sequence),
|
||
|
use:
|
||
|
|
||
|
CONFIG GIF_RESET_MODE 1
|
||
|
|
||
|
The gif format can not match 30fps exactly, so PICO-8 instead uses the closest match: 33.3fps.
|
||
|
|
||
|
If you have trouble saving to the desktop, try configuring an alternative desktop path in
|
||
|
config.txt
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
Sharing Cartridges
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
There are three ways to share carts made in PICO-8:
|
||
|
|
||
|
1. Share the .p8 or .p8.png file directly with other PICO-8 users
|
||
|
|
||
|
Type FOLDER to open the current folder in your host operating system.
|
||
|
|
||
|
2. Post the cart on the Lexaloffe BBS to get a web-playable version
|
||
|
|
||
|
http://www.lexaloffle.com/pico-8.php?page=submit
|
||
|
|
||
|
3. Export the cartridge to a stand-alone html/js or native binary player (see the exporters
|
||
|
section for details)
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
SPLORE
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
SPLORE is a built-in utility for browsing and organising both local and bbs (online)
|
||
|
cartridges. Type SPLORE [enter] to launch it, or launch PICO-8 with -splore.
|
||
|
|
||
|
It is possible to control SPLORE entirely with a joystick:
|
||
|
|
||
|
LEFT and RIGHT to navigate lists of cartridges
|
||
|
UP AND DOWN to select items in each list
|
||
|
X,O or MENU to launch the cartridge
|
||
|
|
||
|
While inside a cart, press MENU to favourite a cartridge or exit to splore. If you're using a
|
||
|
keyboard, it's also possible to press F to favourite an item while it is selected in the
|
||
|
cartridge list view.
|
||
|
|
||
|
When viewing a list of BBS carts, use the top list item to re-download a list of cartridges. If
|
||
|
you are offline, the last downloaded list is displayed, and it is still possible to play any
|
||
|
cartridges you have downloaded.
|
||
|
|
||
|
If you have installed PICO-8 on a machine with no internet access, you can also use
|
||
|
INSTALL_GAMES to add a small selection of pre-installed BBS carts to /games
|
||
|
|
||
|
====================================================================================================
|
||
|
Editing Tools
|
||
|
====================================================================================================
|
||
|
|
||
|
Press ESC to toggle between console and editor.<br> Click editing mode tabs at top right to
|
||
|
switch or press ALT+LEFT/RIGHT.
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
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 to search for text in the current tab
|
||
|
CTRL-G to repeat the last search again
|
||
|
CTRL-L to jump to a line number
|
||
|
CTRL-UP, DOWN to jump to start or end
|
||
|
ALT-UP, DOWN to navigate to the previous, next function
|
||
|
CTRL-LEFT, RIGHT to jump by word
|
||
|
CTRL-W,E to jump to start or end of current line
|
||
|
CTRL-D to duplicate current line
|
||
|
TAB to indent a selection (shift to un-indent)
|
||
|
CTRL-B to comment / uncomment selected block
|
||
|
CTRL-U to get help on the keyword under the cursor
|
||
|
|
||
|
To enter special characters that represent buttons (and other glyphs), use SHIFT-L,R,U,D,O,X
|
||
|
There are 3 additional font entry modes that can be toggled:
|
||
|
|
||
|
CTRL_J Hiragana // type romaji equivalents (ka, ki, ku..)
|
||
|
CTRL-K Katakana // + shift-0..9 for extra symbols
|
||
|
CTRL-P Puny font // hold shift for the standard font
|
||
|
|
||
|
By default, puny font characters are encoded as unicode replacements when copying/pasting,
|
||
|
and both upper and lower case ASCII characters are pasted as regular PICO-8 characters. To
|
||
|
copy/paste puny characters as uppercase ASCII, make sure puny mode (CTRL-P) is on.
|
||
|
|
||
|
:: Code Tabs
|
||
|
|
||
|
Click the [+] button at the top to add a new tab. Navigate tabs by left-clicking, or with
|
||
|
CTRL-TAB, SHIFT-CTRL-TAB. To remove the last tab, delete any contents and then moving off
|
||
|
it (CTRL-A, DEL, CTRL-TAB)
|
||
|
|
||
|
When running a cart, a single program is generated by concatenating all tabs in order.
|
||
|
|
||
|
:: Code Limits
|
||
|
|
||
|
The number of code tokens is shown at the bottom right. One program can have a maximum of
|
||
|
8192 tokens. Each token is a word (e.g. variable name) or operator. Pairs of brackets, and
|
||
|
strings each count as 1 token. commas, periods, LOCALs, semi-colons, ENDs, and comments are
|
||
|
not counted.
|
||
|
|
||
|
Right click to toggle through other stats (character count, compressed size). If a limit is
|
||
|
reached, a warning light will flash. This can be disabled by right-clicking.
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
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
|
||
|
sprite-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 plot pixels, or use RMB to select the colour under the
|
||
|
cursor.
|
||
|
|
||
|
All operations apply only to the visible area, or the section if there is one.
|
||
|
|
||
|
Hold CTRL to search and replace a colour.
|
||
|
|
||
|
:: Stamp Tool
|
||
|
|
||
|
Click to stamp whatever is in the copy buffer. Hold CTRL to treat colour 0 (black) as
|
||
|
transparent.
|
||
|
|
||
|
:: Select Tool (shortcut: SHIFT or S)
|
||
|
|
||
|
Click and drag to create a rectangular selection. To remove the selection, press ENTER or
|
||
|
click anywhere.
|
||
|
|
||
|
If a pixel-wise selection is not present, many operations are instead applied to a
|
||
|
sprite-wise selection, or the visible view. To select sprites, shift-drag in the sprite
|
||
|
navigator. To select the sprite sheet press CTRL-A (repeat to toggle off the bottom half
|
||
|
shared with map data)
|
||
|
|
||
|
:: Pan Tool (shortcut: SPACE)
|
||
|
|
||
|
Click and drag to move around the sprite sheet.
|
||
|
|
||
|
:: Fill Tool
|
||
|
|
||
|
Fill with the current colour. This applies only to the current selection, or the visible
|
||
|
area if there is no selection.
|
||
|
|
||
|
:: Shape Tools
|
||
|
|
||
|
Click the tool button to cycle through: oval, rectangle, line options.
|
||
|
|
||
|
Hold CTRL to get a filled oval or rectangle.<br> Hold SHIFT to snap to circle, square, or
|
||
|
low-integer-ratio line.
|
||
|
|
||
|
:: Extra keys
|
||
|
|
||
|
CTRL-Z: Undo
|
||
|
CTRL-C/X: Copy/Cut selected area or selected sprites
|
||
|
CTRL-V: Paste to current sprite location
|
||
|
Q/A,W/Z: Switch to previous/next sprite
|
||
|
1,2: Switch to previous/next colour
|
||
|
TAB: Toggle fullscreen view
|
||
|
Mousewheel or < and > to zoom (centered in fullscreen)
|
||
|
CTRL-H to toggle hex view (shows sprite index in hexadecimal)
|
||
|
CTRL-G to toggle black grid lines when zoomed in
|
||
|
|
||
|
:: Operations on selected area or selected sprites
|
||
|
|
||
|
F: Flip sprite horizontally
|
||
|
V: Flip sprite vertically
|
||
|
R: Rotate (requires a square selection)
|
||
|
Cursor keys to shift (loops if sprite selection)
|
||
|
DEL/BACKSPACE to clear selected area
|
||
|
|
||
|
:: Sprite Flags
|
||
|
|
||
|
The 8 coloured circles are sprite flags for the current sprite. These have no particular
|
||
|
meaning, but can be accessed using the @FGET() / @FSET() functions. They are indexed from 0
|
||
|
starting from the left.
|
||
|
|
||
|
See @FSET() for more information.
|
||
|
|
||
|
:: Loading .png files into the sprite sheet
|
||
|
|
||
|
To load a png file of any size into the sprite sheet, first select the sprite that should
|
||
|
be the top-left corner destination, and then either type "IMPORT IMAGE_FILE.PNG" or drag
|
||
|
and drop the image file into the PICO-8 window. In both cases, the image is colour-fitted
|
||
|
to the current display palette.
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
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.
|
||
|
|
||
|
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.
|
||
|
|
||
|
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 Mousewheel or < and > to zoom
|
||
|
(centered in fullscreen) CTRL-H to toggle hex view (shows tile values and sprite index in
|
||
|
hexadecimal)
|
||
|
|
||
|
Moving sprites in the sprite sheet without breaking reference to them in the map is a little
|
||
|
tricky, but possible:
|
||
|
|
||
|
1. Press ENTER to clear any map selection
|
||
|
2. Select the sprites you would like to move (while still in map view), and press Ctrl-X
|
||
|
3. Select the area of the map you would like to alter (defaults to the top half of the map)
|
||
|
// press ctrl-A twice to select the full map including shared memory
|
||
|
4. Select the destination sprite (also while still in map view) and press Ctrl-V
|
||
|
|
||
|
// Note: this operation modifies the undo history for both the map and sprite editors, but
|
||
|
// PICO-8 will try to keep them in sync where possible. Otherwise, changes caused by moving
|
||
|
// map sprites can be reverted by also manually undoing in the sprite editor.
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
SFX Editor
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
There are 64 SFX ("sound effects") in a cartridge, used for both sound and music.
|
||
|
|
||
|
Each SFX has 32 notes, and each note has:
|
||
|
A frequency (C0..C5)
|
||
|
An instrument (0..7)
|
||
|
A volume (0..7)
|
||
|
An effect (0..7)
|
||
|
|
||
|
Each SFX also has these properties:
|
||
|
|
||
|
A play speed (SPD) : the number of 'ticks' to play each note for.
|
||
|
// This means that 1 is fastest, 3 is 3x as slow, etc.
|
||
|
|
||
|
Loop start and end : this is the note index to loop back and to
|
||
|
// Looping is turned off when the start index >= end index
|
||
|
|
||
|
When only the first of the 2 numbers is used (and the second one is 0), it is taken to mean
|
||
|
the number of notes to be played. This is normally not needed for sound effects (you can
|
||
|
just leave the remaining notes empty), but is useful for controlling music playback.
|
||
|
|
||
|
There are 2 modes for editing/viewing a SFX: Pitch mode (more suitable for sound effects) and
|
||
|
tracker mode (more suitable for music). The mode can be changed using the top-left buttons, or
|
||
|
toggled with TAB.
|
||
|
|
||
|
:: Pitch Mode
|
||
|
|
||
|
Click and drag on the pitch area to set the frequency for each note, using the currently
|
||
|
selected instrument (indicated by colour).
|
||
|
|
||
|
Hold shift to apply only the selected instrument.
|
||
|
Hold CTRL to snap entered notes to the C minor pentatonic scale.
|
||
|
Right click to grab the instrument of that note.
|
||
|
|
||
|
:: Tracker Mode
|
||
|
|
||
|
Each note shows: frequency octave instrument volume effect
|
||
|
To enter a note, use q2w3er5t6y7ui zsxdcvgbhnjm (piano-like layout)
|
||
|
Hold shift when entering a note to transpose -1 octave .. +1 octave
|
||
|
New notes are given the selected instrument/effect values
|
||
|
To delete a note, use backspace or set the volume to 0
|
||
|
|
||
|
Click and then shift-click to select a range that can be copied (CTRL-C) and pasted
|
||
|
(CTRL-V). Note that only the selected attributes are copied. Double-click to select all
|
||
|
attributes of a single note.
|
||
|
|
||
|
Navigation:
|
||
|
PAGEUP/DOWN or CTRL-UP/DOWN to skip up or down 4 notes
|
||
|
HOME/END to jump to the first or last note
|
||
|
CTRL-LEFT/RIGHT to jump across columns
|
||
|
|
||
|
:: Controls for both modes
|
||
|
|
||
|
- + to navigate the current SFX
|
||
|
SPACE to play/stop
|
||
|
SHIFT-SPACE to play from the current SFX quarter (group of 8 notes)
|
||
|
A to release a looping sample
|
||
|
Left click or right click to increase / decrease the SPD or LOOP values
|
||
|
// Hold shift when clicking to increase / decrease by 4
|
||
|
// Alternatively, click and drag left/right or up/down
|
||
|
Shift-click an instrument, effect, or volume to apply to all notes.
|
||
|
|
||
|
:: Effects
|
||
|
|
||
|
0 none
|
||
|
1 slide // Slide to the next note and volume
|
||
|
2 vibrato // Rapidly vary the pitch within one quarter-tone
|
||
|
3 drop // Rapidly drop the frequency to very low values
|
||
|
4 fade in // Ramp the volume up from 0
|
||
|
5 fade out // Ramp the volume down to 0
|
||
|
6 arpeggio fast // Iterate over groups of 4 notes at speed of 4
|
||
|
7 arpeggio slow // Iterate over groups of 4 notes at speed of 8
|
||
|
|
||
|
If the SFX speed is <= 8, arpeggio speeds are halved to 2, 4
|
||
|
|
||
|
:: Filters
|
||
|
|
||
|
Each SFX has 5 filter switches that can be accessed while in tracker mode:
|
||
|
|
||
|
NOIZ: Generate pure white noise (applies only to instrument 6)
|
||
|
BUZZ: Various alterations to the waveform to make it sound more buzzy
|
||
|
DETUNE-1: Detunes a second voice to create a flange-like effect
|
||
|
DETUNE-2: Various second voice tunings, mostly up or down an octave
|
||
|
REVERB: Apply an echo with a delay of 2 or 4 ticks
|
||
|
DAMPEN: Low pass filter at 2 different levels
|
||
|
|
||
|
When BUZZ is used with instrument 6, and NOIZ is off, pure brown noise is generated.
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
Music Editor
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
Music in PICO-8 is controlled by a sequence of 'patterns'. Each pattern is a list of 4 numbers
|
||
|
indicating which SFX will be played on that channel.
|
||
|
|
||
|
:: Flow control
|
||
|
|
||
|
Playback flow can be controlled using the 3 buttons at the top right.
|
||
|
|
||
|
When a pattern has finished playing, the next pattern is played unless:
|
||
|
|
||
|
- there is no data left to play (music stops)
|
||
|
- a STOP command is set on that pattern (the third button)
|
||
|
- a LOOP BACK command is set (the 2nd button), in which case the music player searches
|
||
|
back for a pattern with the LOOP START command set (the first button) or returns to
|
||
|
pattern 0 if none is found.
|
||
|
|
||
|
When a pattern has SFXes with different speeds, the pattern finishes playing when the left-most
|
||
|
non-looping channel has finished playing. This can be used to set up double-time drum beats or
|
||
|
unusual polyrhythms.
|
||
|
|
||
|
For time signatures like 3/4 where less than 32 rows should be played before jumping to the
|
||
|
next pattern, the length of a SFX can be set by adjusting only the first loop position and
|
||
|
leaving the second one as zero. This will show up in the sfx editor as "LEN" (for "Length")
|
||
|
instead of "LOOP".
|
||
|
|
||
|
:: Copying and Pasting Music
|
||
|
|
||
|
To select a range of patterns: click once on the first pattern in the pattern navigator, then
|
||
|
shift-click on the last pattern. Selected patterns can be copied and pasted with CTRL-C and
|
||
|
CTRL-V. When pasting into another cartridge, the SFX that each pattern points to will also be
|
||
|
pasted (possibly with a different index) if it does not already exist.
|
||
|
|
||
|
:: SFX Instruments
|
||
|
|
||
|
In addition to the 8 built-in instruments, custom instruments can be defined using the first 8
|
||
|
SFX. Use the toggle button to the right of the instruments to select an index, which will show
|
||
|
up in the instrument channel as green instead of pink.
|
||
|
|
||
|
When an SFX instrument note is played, it essentially triggers that SFX, but alters the note's
|
||
|
attributes:
|
||
|
|
||
|
Pitch is added relative to C2
|
||
|
Volume is multiplied
|
||
|
Effects are applied on top of the SFX instrument's effects
|
||
|
Any filters that are on in the SFX instrument are enabled for that note
|
||
|
|
||
|
For example, a simple tremolo effect could be implemented by defining an instrument in SFX 0
|
||
|
that rapidly alternates between volume 5 and 2. When using this instrument to play a note, the
|
||
|
volume can further be altered as usual (via the volume channel or using the fade in/out
|
||
|
effects). In this way, SFX instruments can be used to control combinations of detailed changes
|
||
|
in volume, pitch and texture.
|
||
|
|
||
|
SFX instruments are only retriggered when the pitch changes, or the previous note has zero
|
||
|
volume. This is useful for instruments that change more slowly over time. For example: a bell
|
||
|
that gradually fades out. To invert this behaviour, effect 3 (normally 'drop') can be used when
|
||
|
triggering the note. All other effect values have their usual meaning when triggering SFX
|
||
|
instruments.
|
||
|
|
||
|
====================================================================================================
|
||
|
Exporters / Importers
|
||
|
====================================================================================================
|
||
|
|
||
|
The EXPORT command can be used to generate png, wav files and stand-alone html and native binary
|
||
|
cartridge applications. The output format is inferred from the filename extension (e.g. .png).
|
||
|
|
||
|
You are free to distribute and use exported cartridges and data as you please, provided that you
|
||
|
have permission from the cartridge author and contributors.
|
||
|
|
||
|
:: Sprite Sheet / Label (.png)
|
||
|
|
||
|
> IMPORT BLAH.PNG -- EXPECTS 128X128 PNG AND COLOUR-FITS TO THE PICO-8 PALETTE
|
||
|
> EXPORT BLAH.PNG -- USE THE "FOLDER" COMMAND TO LOCATE THE EXPORTED PNG
|
||
|
|
||
|
When importing, -x and -y switches can be used to specify the target location in pixels: -s can
|
||
|
be used to shrink the image (3 means scale from 384x384 -> 128x128)
|
||
|
|
||
|
> IMPORT BLAH.PNG -X 16 -Y 16 -S 3
|
||
|
|
||
|
Use the -l switch with IMPORT and EXPORT to instead read and write from the cartridge's label:
|
||
|
|
||
|
> IMPORT -L BLAH.PNG
|
||
|
|
||
|
When importing spritesheets or labels, the palette is colour-fitted to the current draw state
|
||
|
palette.
|
||
|
|
||
|
:: SFX and Music (.wav)
|
||
|
|
||
|
To export music from the current pattern (when editor mode is MUSIC), or the current SFX:
|
||
|
|
||
|
> EXPORT FOO.WAV
|
||
|
|
||
|
To export all SFXs as foo0.wav, foo1.wav .. foo63.wav:
|
||
|
|
||
|
> EXPORT FOO%D.WAV
|
||
|
|
||
|
:: MAP and CODE
|
||
|
|
||
|
A cartridges map or source code can be exported as a single image named .map.png or .lua.png:
|
||
|
|
||
|
> EXPORT FOO.MAP.PNG
|
||
|
> EXPORT FOO.LUA.PNG
|
||
|
|
||
|
Map images are 1024x512 (128x32 8x8 sprites). Lua images are sized to fit, but each line is
|
||
|
fixed (and cropped) at 192 pixels wide.
|
||
|
|
||
|
:: Cartridges (.p8, .p8.png, .p8.rom)
|
||
|
|
||
|
Using EXPORT to save a cartridge is the same as using SAVE, but without changing the current
|
||
|
working cartridge. This can be useful for example, to save a copy in .p8.png format for
|
||
|
distribution without accidentally continuing to make changes to that file instead of the
|
||
|
original .p8 file.
|
||
|
|
||
|
EXPORT can also be used to perform cartridge file format conversions from commandline. For
|
||
|
example, from a Linux shell:
|
||
|
|
||
|
> pico8 foo.p8 -export foo.p8.png
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
Web Applications (.html)
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
To generate a stand-alone html player (mygame.html, mygame.js):
|
||
|
|
||
|
> EXPORT MYGAME.HTML
|
||
|
|
||
|
Or just the .js file:
|
||
|
|
||
|
> EXPORT MYGAME.JS
|
||
|
|
||
|
Use -f to write the files to a folder called mygame_html, using index.html instead of
|
||
|
mygame.html
|
||
|
|
||
|
> EXPORT -F MYGAME.HTML
|
||
|
|
||
|
Optionally provide a custom html template with the -p switch:
|
||
|
|
||
|
> EXPORT MYGAME.HTML -P ONE_BUTTON
|
||
|
|
||
|
This will use the file {application data}/pico-8/plates/one_button.html as the html shell,
|
||
|
replacing a special string "##js_file##" (without quotes), with the .js filename, and
|
||
|
optionally replacing the string "##label_file##" with the cart's label image as a data url.
|
||
|
|
||
|
Use -w to export as .wasm + .js:
|
||
|
|
||
|
> EXPORT -W MYGAME.HTML
|
||
|
|
||
|
When exported as .wasm, the page needs to be served by a webserver, rather than just opening it
|
||
|
directly from the local file system in a browser. For most purposes, the default .js export is
|
||
|
fine, but .wasm is slightly smaller and faster.
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
Binary Applications (.bin)
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
To generate stand-alone executables for Windows, Linux (64-bit), Mac and Raspberry Pi:
|
||
|
|
||
|
> EXPORT MYGAME.BIN
|
||
|
|
||
|
By default, the cartridge label is used as an icon with no transparency. To specify an icon
|
||
|
from the sprite sheet, use -i and optionally -s and/or -c to control the size and
|
||
|
transparency.
|
||
|
|
||
|
-I N Icon index N with a default transparent colour of 0 (black).
|
||
|
-S N Size NxN sprites. Size 3 would be produce a 24x24 icon.
|
||
|
-C N Treat colour N as transparent. Use 16 for no transparency.
|
||
|
|
||
|
For example, to use a 2x2 sprite starting at index 32 in the sprite sheet, using colour 12 as
|
||
|
transparent:
|
||
|
|
||
|
> EXPORT -I 32 -S 2 -C 12 MYGAME.BIN
|
||
|
|
||
|
To include an extra file in the output folders and archives, use the -E switch:
|
||
|
|
||
|
> EXPORT -E README.TXT MYGAME.BIN
|
||
|
|
||
|
Windows file systems do not support the file metadata needed to create a Linux or Mac
|
||
|
executable. PICO-8 works around this by exporting zip files in a way that preserves the file
|
||
|
attributes. It is therefore recommended that you distribute the outputted zip files as-is to
|
||
|
ensure users on other operating systems can run them. Otherwise, a Linux user who then
|
||
|
downloads the binaries may need to "chmod +x mygame" the file to run it, and Mac user would
|
||
|
need to "chmod +x mygame.app/Contents/MacOS/mygame"
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
Uploading to itch.io
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
If you would like to upload your exported cartridge to itch.io as playable html:
|
||
|
|
||
|
1. From inside PICO-8: EXPORT -F MYGAME.HTML
|
||
|
2. Create a new project from your itch dashboard.
|
||
|
3. Zip up the folder and upload it (set "This file will be played in the browser")
|
||
|
4. Embed in page, with a size of 750px x 680px.
|
||
|
5. Set "Mobile Friendly" on (default orientation) and "Automatically start on page load" on.
|
||
|
// no need for the fullscreen button as the default PICO-8 template has its own.
|
||
|
6. Set the background (BG2) to something dark (e.g. #232323) and the text to something light (#cccccc)
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
Exporting Multiple Cartridges
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
Up to 16 cartridges can be bundled together by passing them to EXPORT, when generating
|
||
|
stand-alone html or native binary players.
|
||
|
|
||
|
> EXPORT MYGAME.HTML DAT1.P8 DAT2.P8 GAME2.P8
|
||
|
|
||
|
During runtime, the extra carts can be accessed as if they were local files:
|
||
|
|
||
|
RELOAD(0,0,0X2000, "DAT1.P8") -- LOAD SPRITESHEET FROM DAT1.P8
|
||
|
LOAD("GAME2.P8") -- LOAD AND RUN ANOTHER CART
|
||
|
|
||
|
Exported cartridges are unable to load and run BBS cartridges e.g. via LOAD("#FOO")
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
Running EXPORT from the host operating system
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
Use the -export switch when launching PICO-8 to run the exporter in headless mode. File paths
|
||
|
are relative to the current directory rather than the PICO-8 file system.
|
||
|
|
||
|
Parameters to the EXPORT command are passed along as a single (lowercase) string:
|
||
|
|
||
|
pico8 mygame.p8 -export "-i 32 -s 2 -c 12 mygame.bin dat0.p8 dat1.p8"
|
||
|
|
||
|
====================================================================================================
|
||
|
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 out about proper Lua, see www.lua.org.
|
||
|
|
||
|
:: Comments
|
||
|
|
||
|
-- USE TWO DASHES LIKE THIS TO WRITE A COMMENT
|
||
|
--[[ MULTI-LINE
|
||
|
COMMENTS ]]
|
||
|
|
||
|
:: 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.99999
|
||
|
|
||
|
Hexadecimal notation with optional fractional parts can be used:
|
||
|
|
||
|
?0x11 -- 17
|
||
|
?0x11.4000 -- 17.25
|
||
|
|
||
|
Numbers written in decimal are rounded to the closest fixed point value. To see the 32-bit
|
||
|
hexadecimal representation, use PRINT(TOSTR(VAL,TRUE)):
|
||
|
|
||
|
?TOSTR(-32768,TRUE) -- 0x8000.0000
|
||
|
?TOSTR(32767.99999,TRUE) -- 0X7FFF.FFFF
|
||
|
|
||
|
Dividing by zero evaluates to 0x7fff.ffff if positive, or -0x7fff.ffff if negative.
|
||
|
|
||
|
:: Conditionals
|
||
|
|
||
|
IF NOT B THEN
|
||
|
PRINT("B IS FALSE")
|
||
|
ELSE
|
||
|
PRINT("B IS NOT FALSE")
|
||
|
END
|
||
|
|
||
|
-- with ELSEIF
|
||
|
|
||
|
IF X == 0 THEN
|
||
|
PRINT("X IS 0")
|
||
|
ELSEIF X < 0 THEN
|
||
|
PRINT("X IS NEGATIVE")
|
||
|
ELSE
|
||
|
PRINT("X IS POSITIVE")
|
||
|
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
|
||
|
|
||
|
Loop ranges are inclusive:
|
||
|
|
||
|
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
|
||
|
|
||
|
Variables declared as LOCAL are scoped to their containing block of code (for example, inside a
|
||
|
FUNCTION, a FOR loop, or IF THEN END statement).
|
||
|
|
||
|
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
|
||
|
|
||
|
But if you prefer 0-based arrays, just write something the zeroth slot:
|
||
|
|
||
|
> A = {[0]=10,11,12,13,14}
|
||
|
|
||
|
Tables with 1-based integer indexes are special though. The length of such an array can be
|
||
|
found with the # operator, and PICO-8 uses such arrays to implement ADD, DEL, DELI, ALL and
|
||
|
FOREACH functions.
|
||
|
|
||
|
> PRINT(#A) -- 4
|
||
|
> ADD(A, 15)
|
||
|
> PRINT(#A) -- 5
|
||
|
|
||
|
Indexes that are strings can be written using dot notation
|
||
|
|
||
|
PLAYER = {}
|
||
|
PLAYER.X = 2 -- is equivalent to PLAYER["X"]
|
||
|
PLAYER.Y = 3
|
||
|
|
||
|
See the @{Table_Functions} section for more details.
|
||
|
|
||
|
:: PICO-8 Shorthand
|
||
|
|
||
|
PICO-8 also allows several non-standard, shorter ways to write common patterns.
|
||
|
|
||
|
1. IF THEN END statements, and WHILE THEN END can be written on a single line with:
|
||
|
|
||
|
IF (NOT B) I=1 J=2
|
||
|
|
||
|
Is equivalent to:
|
||
|
|
||
|
IF NOT B THEN I=1 J=2 END
|
||
|
|
||
|
Note that brackets around the short-hand condition are required.
|
||
|
|
||
|
2. Assignment operators
|
||
|
|
||
|
Shorthand assignment operators can also be used if the whole statement is on one line. They can
|
||
|
be constructed by appending a '=' to any binary operator, including arithmetic (+=, -= ..),
|
||
|
bitwise (&=, |= ..) or the string concatenation operator (..=)
|
||
|
|
||
|
A += 2 -- EQUIVALENT TO: A = A + 2
|
||
|
|
||
|
// note that the LHS appears twice, so for TBL[FN()]+=1, FN() will be called twice.
|
||
|
|
||
|
3. != operator
|
||
|
|
||
|
Not shorthand, but pico-8 also accepts != instead of ~= for "not equal to"
|
||
|
|
||
|
PRINT(1 != 2) -- TRUE
|
||
|
PRINT("FOO" == "FOO") -- TRUE (STRING ARE INTERNED)
|
||
|
|
||
|
====================================================================================================
|
||
|
PICO-8 Program Structure
|
||
|
====================================================================================================
|
||
|
|
||
|
When a PICO-8 programs runs, all of the code from tabs is concatenated (from left to right) and
|
||
|
executed. It is possible to provide your own main loop manually, but typically PICO-8 programs
|
||
|
use 3 special functions that, if defined by the author, are called during program execution:
|
||
|
|
||
|
|
||
|
_UPDATE() -- Called once per update at 30fps.
|
||
|
|
||
|
|
||
|
_DRAW() -- Called once per visible frame
|
||
|
|
||
|
|
||
|
_INIT() -- Called once on program startup.
|
||
|
|
||
|
A simple program that uses all three might look this:
|
||
|
|
||
|
FUNCTION _INIT()
|
||
|
-- ALWAYS START ON WHITE
|
||
|
COL = 7
|
||
|
END
|
||
|
|
||
|
FUNCTION _UPDATE()
|
||
|
-- PRESS X FOR A RANDOM COLOUR
|
||
|
IF (BTNP(5)) COL = 8 + RND(8)
|
||
|
END
|
||
|
|
||
|
FUNCTION _DRAW()
|
||
|
CLS(1)
|
||
|
CIRCFILL(64,64,32,COL)
|
||
|
END
|
||
|
|
||
|
_DRAW() is normally called at 30fps, but if it can not complete in time, PICO-8 will attempt to
|
||
|
run at 15fps and call _UPDATE() twice per visible frame to compensate.
|
||
|
|
||
|
:: Running PICO-8 at 60fps
|
||
|
|
||
|
|
||
|
_UPDATE60()
|
||
|
|
||
|
When _UPDATE60() Is defined instead of _UPDATE(), PICO-8 will run in 60fps mode:
|
||
|
|
||
|
- both _UPDATE60() and _DRAW() are called at 60fps<br> - half the PICO-8 CPU is available per
|
||
|
frame before dropping down to 30fps
|
||
|
|
||
|
Note that not all host machines are capable of running at 60fps. Older machines, and / or web
|
||
|
versions might also request PICO-8 to run at 30 fps (or 15 fps), even when the PICO-8 CPU is
|
||
|
not over capacity. In this case, multiple _UPDATE60 calls are made for every _DRAW call in the
|
||
|
same way.
|
||
|
|
||
|
:: #INCLUDE
|
||
|
|
||
|
Source code can be injected into a program at cartridge boot (but not during runtime), using
|
||
|
"#INCLUDE FILENAME", where FILENAME is either a plaintext file (containing Lua code), a tab
|
||
|
from another cartridge, or all tabs from another cartridge:
|
||
|
|
||
|
#INCLUDE SOMECODE.LUA
|
||
|
#INCLUDE ONETAB.P8:1
|
||
|
#INCLUDE ALLTABS.P8
|
||
|
|
||
|
When the cartridge is run, the contents of each included file is treated as if it had been
|
||
|
pasted into the editor in place of that line.
|
||
|
|
||
|
- Filenames are relative to the current cartridge (so, need to save first)<br> - Includes
|
||
|
are not performed recursively.<br> - Normal character count and token limits apply.
|
||
|
|
||
|
When a cartridge is saved as .P8.PNG, or exported to a binary, any included files are
|
||
|
flattened and saved with the cartridge so that there are no external dependencies.
|
||
|
|
||
|
#INCLUDE can be used for things like:
|
||
|
|
||
|
- Sharing code between cartridge (libraries or common multi-cart code)<br> - Using an
|
||
|
external code editor without needing to edit the .p8 file directly.<br> - Treating a
|
||
|
cartridge as a data file that loads a PICO-8 editing tool to modify it.<br> - Loading and
|
||
|
storing data generated by an external (non-PICO-8) tool.
|
||
|
|
||
|
:: Quirks of PICO-8
|
||
|
|
||
|
Common gotchas to watch out for:
|
||
|
|
||
|
- The bottom half of the sprite sheet 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 have limited accuracy and range; the minimum step between numbers is
|
||
|
approximately 0.00002 (0x0.0001), with a range of -32768 (-0x8000) to approximately 32767.99999
|
||
|
(0x7fff.ffff)<br> // If you add 1 to a counter each frame, it will overflow after around 18
|
||
|
minutes!
|
||
|
|
||
|
- Lua arrays are 1-based by default, not 0-based. FOREACH starts at TBL[1], not TBL[0].
|
||
|
|
||
|
- @COS() and @SIN() take 0..1 instead of 0..PI*2, and @SIN() is inverted.
|
||
|
|
||
|
- @SGN(0) returns 1.
|
||
|
|
||
|
:: CPU
|
||
|
|
||
|
Although PICO-8 does not have a clearly defined CPU, there is a virtual CPU speed of 8MHz,
|
||
|
where each lua vm instruction costs around 2 cycles. Built-in operations like drawing sprites
|
||
|
also have a CPU cost. This means that a PICO-8 cartridge made on a host machine with a powerful
|
||
|
CPU can still be guaranteed to run (reasonably) well on much slower machines, and to not drain
|
||
|
too much battery on phones / when running on the web.
|
||
|
|
||
|
To view the CPU load while a cartridge is running, press CTRL-P to toggle a CPU meter, or print
|
||
|
out @STAT(1) at the end of each frame.
|
||
|
|
||
|
====================================================================================================
|
||
|
API Reference
|
||
|
====================================================================================================
|
||
|
|
||
|
PICO-8 is built on the Lua programming 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])
|
||
|
|
||
|
Note that PICO-8 does not have upper or lower case characters -- if you are editing a .p8 or
|
||
|
.lua file directly, function names should all be in lower case.
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
System
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
System functions called from commandline can omit the usual brackets and string quotes. For
|
||
|
example, instead of LOAD("BLAH.P8"), it is possible to write:
|
||
|
|
||
|
>LOAD BLAH.P8
|
||
|
|
||
|
|
||
|
LOAD(FILENAME, [BREADCRUMB], [PARAM_STR])
|
||
|
|
||
|
SAVE(FILENAME)
|
||
|
|
||
|
Load or save a cartridge
|
||
|
|
||
|
When loading from a running cartridge, the loaded cartridge is immediately run with
|
||
|
parameter string PARAM_STR (accessible with STAT(6)), and a menu item is inserted and named
|
||
|
BREADCRUMB, that returns the user to the previous cartridge.
|
||
|
|
||
|
Filenames that start with '#' are taken to be a BBS cart id, that is immediately downloaded
|
||
|
and run:
|
||
|
|
||
|
> LOAD("#MYGAME_LEVEL2", "BACK TO MAP", "LIVES="..LIVES)
|
||
|
|
||
|
If the id is the cart's parent post, or a revision number is not specified, then the latest
|
||
|
version is fetched. BBS carts can be loaded from other BBS carts or local carts, but not
|
||
|
from exported carts.
|
||
|
|
||
|
|
||
|
FOLDER
|
||
|
|
||
|
Open the carts folder in the host operating system.
|
||
|
|
||
|
|
||
|
LS([DIRECTORY])
|
||
|
|
||
|
List .p8 and .p8.png files in given directory (folder), relative to the current directory.
|
||
|
Items that are directories end in a slash (e.g. "foo/").
|
||
|
|
||
|
When called from a running cartridge, LS can only be used locally and returns a table of
|
||
|
the results. When called from a BBS cart, LS returns nil.
|
||
|
|
||
|
Directories can only resolve inside of PICO-8's virtual drive; LS("..") from the root
|
||
|
directory will resolve to the root directory.
|
||
|
|
||
|
|
||
|
RUN([PARAM_STR])
|
||
|
|
||
|
Run from the start of the program.
|
||
|
|
||
|
RUN() Can be called from inside a running program to reset.
|
||
|
|
||
|
When PARAM_STR is supplied, it can be accessed during runtime with STAT(6)
|
||
|
|
||
|
|
||
|
STOP([MESSAGE])
|
||
|
|
||
|
Stop the cart and optionally print a message.
|
||
|
|
||
|
|
||
|
RESUME
|
||
|
|
||
|
Resume the program. Use R for short.
|
||
|
|
||
|
Use a single "." from the commandline to advance a single frame. This enters frame-by-frame
|
||
|
mode, that can be read with stat(110). While frame-by-frame mode is active, entering an
|
||
|
empty command (by pressing enter) advances one frames.
|
||
|
|
||
|
|
||
|
ASSERT(CONDITION, [MESSAGE])
|
||
|
|
||
|
If CONDITION is false, stop the program and print MESSAGE if it is given. This can be
|
||
|
useful for debugging cartridges, by ASSERT()'ing that things that you expect to be true are
|
||
|
indeed true.
|
||
|
|
||
|
ASSERT(ADDR >= 0 AND ADDR <= 0x7FFF, "OUT OF RANGE")
|
||
|
POKE(ADDR, 42) -- THE MEMORY ADDRESS IS OK, FOR SURE!
|
||
|
|
||
|
|
||
|
REBOOT
|
||
|
|
||
|
Reboot the machine Useful for starting a new project
|
||
|
|
||
|
|
||
|
RESET()
|
||
|
|
||
|
Reset the values in RAM from 0x5f00..0x5f7f to their default values. This includes the
|
||
|
palette, camera position, clipping and fill pattern. If you get lost at the command prompt
|
||
|
because the draw state makes viewing text impossible, try typing RESET! It can also be
|
||
|
called from a running program.
|
||
|
|
||
|
|
||
|
INFO()
|
||
|
|
||
|
Print out some information about the cartridge: Code size, tokens, compressed size
|
||
|
|
||
|
Also displayed:
|
||
|
|
||
|
UNSAVED CHANGES When the cartridge in memory differs to the one on disk
|
||
|
EXTERNAL CHANGES When the cartridge on disk has changed since it was loaded
|
||
|
(e.g. by editing the program using a separate text editor)
|
||
|
|
||
|
|
||
|
FLIP()
|
||
|
|
||
|
Flip the back buffer to screen and wait for next frame. This call is not needed when there
|
||
|
is a @_DRAW() or @_UPDATE() callback defined, as the flip is performed automatically. But
|
||
|
when using a custom main loop, a call to FLIP is normally needed:
|
||
|
|
||
|
::_::
|
||
|
CLS()
|
||
|
FOR I=1,100 DO
|
||
|
A=I/50 - T()
|
||
|
X=64+COS(A)*I
|
||
|
Y=64+SIN(A)*I
|
||
|
CIRCFILL(X,Y,1,8+(I/4)%8)
|
||
|
END
|
||
|
FLIP()GOTO _
|
||
|
|
||
|
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, [FILENAME], [OVERWRITE], [SAVE_TO_DESKTOP])
|
||
|
|
||
|
Print a string to the host operating system's console for debugging.
|
||
|
|
||
|
If filename is set, append the string to a file on the host operating system (in the
|
||
|
current directory by default -- use FOLDER to view).
|
||
|
|
||
|
Setting OVERWRITE to true causes that file to be overwritten rather than appended.
|
||
|
|
||
|
Setting SAVE_TO_DESKTOP to true saves to the desktop instead of the current path.
|
||
|
|
||
|
Use a filename of "@clip" to write to the host's clipboard.
|
||
|
|
||
|
Use stat(4) to read the clipboard, but the contents of the clipboard are only available
|
||
|
after pressing CTRL-V during runtime (for security).
|
||
|
|
||
|
|
||
|
TIME()
|
||
|
|
||
|
T()
|
||
|
|
||
|
Returns the number of seconds elapsed since the cartridge was run.
|
||
|
|
||
|
This is not the real-world time, but is calculated by counting the number of times
|
||
|
|
||
|
|
||
|
_UPDATE or @_UPDATE60 is called. Multiple calls of TIME() from the same frame return
|
||
|
|
||
|
the same result.
|
||
|
|
||
|
|
||
|
STAT(X)
|
||
|
|
||
|
Get system status where X is:
|
||
|
|
||
|
0 Memory usage (0..2048)
|
||
|
1 CPU used since last flip (1.0 == 100% CPU)
|
||
|
4 Clipboard contents (after user has pressed CTRL-V)
|
||
|
6 Parameter string
|
||
|
7 Current framerate
|
||
|
|
||
|
46..49 Index of currently playing SFX on channels 0..3
|
||
|
50..53 Note number (0..31) on channel 0..3
|
||
|
54 Currently playing pattern index
|
||
|
55 Total patterns played
|
||
|
56 Ticks played on current pattern
|
||
|
57 (Boolean) TRUE when music is playing
|
||
|
|
||
|
80..85 UTC time: year, month, day, hour, minute, second
|
||
|
90..95 Local time
|
||
|
|
||
|
100 Current breadcrumb label, or nil
|
||
|
110 Returns true when in frame-by-frame mode
|
||
|
|
||
|
Audio values 16..26 are the legacy version of audio state queries 46..56. They only report on
|
||
|
the current state of the audio mixer, which changes only ~20 times a second (depending on the
|
||
|
host sound driver and other factors). 46..56 instead stores a history of mixer state at each
|
||
|
tick to give a higher resolution estimate of the currently audible state.
|
||
|
|
||
|
|
||
|
EXTCMD(CMD_STR, [P1, P2])
|
||
|
|
||
|
Special system command, where CMD_STR is a string:
|
||
|
|
||
|
"pause" request the pause menu be opened
|
||
|
"reset" request a cart reset
|
||
|
"go_back" return to the previous cart if there is one
|
||
|
"label" set cart label
|
||
|
"screen" save a screenshot
|
||
|
"rec" set video start point
|
||
|
"rec_frames" set video start point in frames mode
|
||
|
"video" save a .gif to desktop
|
||
|
"audio_rec" start recording audio
|
||
|
"audio_end" save recorded audio to desktop (no supported from web)
|
||
|
"shutdown" quit cartridge (from exported binary)
|
||
|
"folder" open current working folder on the host operating system
|
||
|
"set_filename" set the filename for screenshots / gifs / audio recordings
|
||
|
"set_title" set the host window title
|
||
|
|
||
|
Some commands have optional number parameters:
|
||
|
|
||
|
"video" and "screen": P1: an integer scaling factor that overrides the system setting.
|
||
|
P2: when > 0, save to the current folder instead of to desktop
|
||
|
|
||
|
"audio_end" P1: when > 0, save to the current folder instead of to desktop
|
||
|
|
||
|
:: Recording GIFs
|
||
|
|
||
|
EXTCMD("REC"), EXTCMD("VIDEO") is the same as using ctrl-8, ctrl-9 and saves a gif to
|
||
|
the desktop using the current GIF_SCALE setting (use CONFIG GIF_SCALE to change).
|
||
|
|
||
|
The two additional parameters can be used to override these defaults:
|
||
|
|
||
|
EXTCMD("VIDEO", 4) -- SCALE *4 (512 X 512)
|
||
|
EXTCMD("VIDEO", 0, 1) -- DEFAULT SCALING, SAVE TO USER DATA FOLDER
|
||
|
|
||
|
The user data folder can be opened with EXTCMD("FOLDER") and defaults to the same path
|
||
|
as the cartridge, or {pico-8 appdata}/appdata/appname for exported binaries.
|
||
|
|
||
|
Due to the nature of the gif format, all gifs are recorded at 33.3fps, and frames
|
||
|
produced by PICO-8 are skipped or duplicated in the gif to match roughly what the user
|
||
|
is seeing. To record exactly one frame each time @FLIP() is called, regardless of the
|
||
|
runtime framerate or how long it took to generate the frame, use:
|
||
|
|
||
|
EXTCMD("REC_FRAMES")
|
||
|
|
||
|
The default filename for gifs (and screenshots, audio) is foo_%d, where foo is the name
|
||
|
of the cartridge, and %d is a number starting at 0 and automatically incremented until
|
||
|
a file of that name does not exist. Use EXTCMD("SET_FILENAME","FOO") to override that
|
||
|
default. If the custom filename includes "%d", then the auto- incrementing number
|
||
|
behaviour is used, but otherwise files are written even if there is an existing file
|
||
|
with the same name.
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
Graphics
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
PICO-8 has a fixed capacity of 128 8x8 sprites, plus another 128 that overlap 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, a drawing colour, and a fill pattern.
|
||
|
|
||
|
The draw state is reset each time a program is run, or by calling @RESET().
|
||
|
|
||
|
Colour 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, [CLIP_PREVIOUS])
|
||
|
|
||
|
Sets the clipping rectangle in pixels. All drawing operations will be clipped to the
|
||
|
rectangle at x, y with a width and height of w,h.
|
||
|
|
||
|
CLIP() to reset.
|
||
|
|
||
|
When CLIP_PREVIOUS is true, clip the new clipping region by the old one.
|
||
|
|
||
|
|
||
|
PSET(X, Y, [COL])
|
||
|
|
||
|
Sets the pixel at x, y to colour index COL (0..15).
|
||
|
|
||
|
When COL is not specified, the current draw colour is used.
|
||
|
|
||
|
FOR Y=0,127 DO
|
||
|
FOR X=0,127 DO
|
||
|
PSET(X, Y, X*Y/8)
|
||
|
END
|
||
|
END
|
||
|
|
||
|
|
||
|
PGET(X, Y)
|
||
|
|
||
|
Returns the colour of a pixel on the screen at (X, Y).
|
||
|
|
||
|
WHILE (TRUE) DO
|
||
|
X, Y = RND(128), RND(128)
|
||
|
DX, DY = RND(4)-2, RND(4)-2
|
||
|
PSET(X, Y, PGET(DX+X, DY+Y))
|
||
|
END
|
||
|
|
||
|
When X and Y are out of bounds, PGET returns 0. A custom return value can be specified
|
||
|
with:
|
||
|
|
||
|
POKE(0x5f36, 0x10)
|
||
|
POKE(0x5f5B, NEWVAL)
|
||
|
|
||
|
|
||
|
SGET(X, Y)
|
||
|
|
||
|
SSET(X, Y, [COL])
|
||
|
|
||
|
Get or set the colour (COL) of a sprite sheet pixel.
|
||
|
|
||
|
When X and Y are out of bounds, SGET returns 0. A custom value can be specified with:
|
||
|
|
||
|
POKE(0x5f36, 0x10)
|
||
|
POKE(0x5f59, NEWVAL)
|
||
|
|
||
|
|
||
|
FGET(N, [F])
|
||
|
|
||
|
FSET(N, [F], VAL)
|
||
|
|
||
|
Get or set the value (VAL) of sprite N's flag F.
|
||
|
|
||
|
F is the flag index 0..7.
|
||
|
|
||
|
VAL is TRUE or FALSE.
|
||
|
|
||
|
The initial state of flags 0..7 are settable in the sprite editor, so can be used to create
|
||
|
custom sprite attributes. It is also possible to draw only a subset of map tiles by
|
||
|
providing a mask in @MAP().
|
||
|
|
||
|
When F is omitted, all flags are retrieved/set as a single 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(STR, [COL])
|
||
|
|
||
|
Print a string STR and optionally set the draw colour to COL.
|
||
|
|
||
|
Shortcut: written on a single line, ? can be used to call print without brackets:
|
||
|
|
||
|
?"HI"
|
||
|
|
||
|
When X, Y are not specified, a newline is automatically appended. This can be omitted by
|
||
|
ending the string with an explicit termination control character:
|
||
|
|
||
|
?"THE QUICK BROWN FOX\0"
|
||
|
|
||
|
Additionally, when X, Y are not specified, printing text below 122 causes the console to
|
||
|
scroll. This can be disabled during runtime with POKE(0x5f36,0x40).
|
||
|
|
||
|
PRINT returns the right-most x position that occurred while printing. This can be used to
|
||
|
find out the width of some text by printing it off-screen:
|
||
|
|
||
|
W = PRINT("HOGE", 0, -20) -- returns 16
|
||
|
|
||
|
See @{Appendix A} (P8SCII) for information about control codes and custom fonts.
|
||
|
|
||
|
|
||
|
CURSOR(X, Y, [COL])
|
||
|
|
||
|
Set the cursor position.
|
||
|
|
||
|
If COL is specified, also set the current colour.
|
||
|
|
||
|
|
||
|
COLOR([COL])
|
||
|
|
||
|
Set the current colour to be used by drawing functions.
|
||
|
|
||
|
If COL is not specified, the current colour is set to 6
|
||
|
|
||
|
|
||
|
CLS([COL])
|
||
|
|
||
|
Clear the screen and reset the clipping rectangle.
|
||
|
|
||
|
COL defaults to 0 (black)
|
||
|
|
||
|
|
||
|
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
|
||
|
|
||
|
If r is negative, the circle is not drawn
|
||
|
|
||
|
|
||
|
OVAL(X0, Y0, X1, Y1, [COL])
|
||
|
|
||
|
OVALFILL(X0, Y0, X1, Y1, [COL])
|
||
|
|
||
|
Draw an oval that is symmetrical in x and y (an ellipse), with the given bounding
|
||
|
rectangle.
|
||
|
|
||
|
|
||
|
LINE(X0, Y0, [X1, Y1, [COL]])
|
||
|
|
||
|
Draw a line from (X0, Y0) to (X1, Y1)
|
||
|
|
||
|
If (X1, Y1) are not given, the end of the last drawn line is used.
|
||
|
|
||
|
LINE() with no parameters means that the next call to LINE(X1, Y1) will only set the end
|
||
|
points without drawing.
|
||
|
|
||
|
CLS()
|
||
|
LINE()
|
||
|
FOR I=0,6 DO
|
||
|
LINE(64+COS(I/6)*20, 64+SIN(I/6)*20, 8+I)
|
||
|
END
|
||
|
|
||
|
|
||
|
RECT(X0, Y0, X1, Y1, [COL])
|
||
|
|
||
|
RECTFILL(X0, Y0, X1, Y1, [COL])
|
||
|
|
||
|
Draw a rectangle or filled rectangle with corners at (X0, Y0), (X1, Y1).
|
||
|
|
||
|
|
||
|
PAL(C0, C1, [P])
|
||
|
|
||
|
PAL() swaps colour c0 for c1 for one of three palette re-mappings (p defaults to 0):
|
||
|
|
||
|
0: Draw Palette
|
||
|
|
||
|
The draw palette re-maps colours when they are drawn. For example, an orange flower
|
||
|
sprite can be drawn as a red flower by setting the 9th palette value to 8:
|
||
|
|
||
|
PAL(9,8) -- draw subsequent orange (colour 9) pixels as red (colour 8)
|
||
|
SPR(1,70,60) -- any orange pixels in the sprite will be drawn with red instead
|
||
|
|
||
|
Changing the draw palette does not affect anything that was already drawn to the
|
||
|
screen.
|
||
|
|
||
|
1: Display Palette
|
||
|
|
||
|
The display palette re-maps the whole screen when it is displayed at the end of a
|
||
|
frame. For example, if you boot PICO-8 and then type PAL(6,14,1), you can see all of
|
||
|
the gray (colour 6) text immediate change to pink (colour 14) even though it has
|
||
|
already been drawn. This is useful for screen-wide effects such as fading in/out.
|
||
|
|
||
|
2: Secondary Palette
|
||
|
|
||
|
Used by @FILLP() for drawing sprites. This provides a mapping from a single 4-bit
|
||
|
colour index to two 4-bit colour indexes.
|
||
|
|
||
|
PAL() resets all palettes to system defaults (including transparency values)
|
||
|
PAL(P) resets a particular palette (0..2) to system defaults
|
||
|
|
||
|
|
||
|
PAL(TBL, [P])
|
||
|
|
||
|
When the first parameter of pal is a table, colours are assigned for each entry. For
|
||
|
example, to re-map colour 12 and 14 to red:
|
||
|
|
||
|
PAL({[12]=9, [14]=8})
|
||
|
|
||
|
Or to re-colour the whole screen shades of gray (including everything that is already
|
||
|
drawn):
|
||
|
|
||
|
PAL({1,1,5,5,5,6,7,13,6,7,7,6,13,6,7,1}, 1)
|
||
|
|
||
|
Because table indexes start at 1, colour 0 is given at the end in this case.
|
||
|
|
||
|
|
||
|
PALT(C, [T])
|
||
|
|
||
|
Set transparency for colour index to T (boolean) Transparency is observed by @SPR(),
|
||
|
@SSPR(), @MAP() AND @TLINE()
|
||
|
|
||
|
PALT(8, TRUE) -- RED PIXELS NOT DRAWN IN SUBSEQUENT SPRITE/TLINE DRAW CALLS
|
||
|
|
||
|
PALT() resets to default: all colours opaque except colour 0
|
||
|
|
||
|
When C is the only parameter, it is treated as a bitfield used to set all 16 values. For
|
||
|
example: to set colours 0 and 1 as transparent:
|
||
|
|
||
|
PALT(0B1100000000000000)
|
||
|
|
||
|
|
||
|
SPR(N, X, Y, [W, H], [FLIP_X], [FLIP_Y])
|
||
|
|
||
|
Draw sprite N (0..255) at position X,Y
|
||
|
|
||
|
W (width) and H (height) are 1, 1 by default and specify how many sprites wide to blit.
|
||
|
|
||
|
Colour 0 drawn as transparent by default (see @PALT())
|
||
|
|
||
|
When FLIP_X is TRUE, flip horizontally.
|
||
|
|
||
|
When FLIP_Y is TRUE, flip vertically.
|
||
|
|
||
|
|
||
|
SSPR(SX, SY, SW, SH, DX, DY, [DW, DH], [FLIP_X], [FLIP_Y]]
|
||
|
|
||
|
Stretch an rectangle of the sprite sheet (sx, sy, sw, sh) to a destination rectangle on the
|
||
|
screen (sx, sy, dw, dh). In both cases, the x and y values are coordinates (in pixels) of
|
||
|
the rectangle's top left corner, with a width of w, h.
|
||
|
|
||
|
Colour 0 drawn as transparent by default (see @PALT())
|
||
|
|
||
|
dw, dh defaults to sw, sh
|
||
|
|
||
|
When FLIP_X is TRUE, flip horizontally.
|
||
|
|
||
|
When FLIP_Y is TRUE, flip vertically.
|
||
|
|
||
|
|
||
|
FILLP(P)
|
||
|
|
||
|
The PICO-8 fill pattern is a 4x4 2-colour tiled pattern observed by: @CIRC() @CIRCFILL()
|
||
|
@RECT() @RECTFILL() @OVAL() @OVALFILL() @PSET() @LINE()
|
||
|
|
||
|
P is a bitfield in reading order starting from the highest bit. To calculate the value of P
|
||
|
for a desired pattern, add the bit values together:
|
||
|
|
||
|
.-----------------------.
|
||
|
|32768|16384| 8192| 4096|
|
||
|
|-----|-----|-----|-----|
|
||
|
| 2048| 1024| 512 | 256 |
|
||
|
|-----|-----|-----|-----|
|
||
|
| 128 | 64 | 32 | 16 |
|
||
|
|-----|-----|-----|-----|
|
||
|
| 8 | 4 | 2 | 1 |
|
||
|
'-----------------------'
|
||
|
|
||
|
For example, FILLP(4+8+64+128+ 256+512+4096+8192) would create a checkerboard pattern.
|
||
|
|
||
|
This can be more neatly expressed in binary: FILLP(0b0011001111001100).
|
||
|
|
||
|
The default fill pattern is 0, which means a single solid colour is drawn.
|
||
|
|
||
|
To specify a second colour for the pattern, use the high bits of any colour parameter:
|
||
|
|
||
|
FILLP(0b0011010101101000)
|
||
|
CIRCFILL(64,64,20, 0x4E) -- brown and pink
|
||
|
|
||
|
Additional settings are given in bits 0b0.111:
|
||
|
|
||
|
0b0.100 Transparency
|
||
|
|
||
|
When this bit is set, the second colour is not drawn
|
||
|
|
||
|
-- checkboard with transparent squares
|
||
|
FILLP(0b0011001111001100.1)
|
||
|
|
||
|
0b0.010 Apply to Sprites
|
||
|
|
||
|
When set, the fill pattern is applied to sprites (spr, sspr, map, tline), using a
|
||
|
colour mapping provided by the secondary palette.
|
||
|
|
||
|
Each pixel value in the sprite (after applying the draw palette as usual) is taken
|
||
|
to be an index into the secondary palette. Each entry in the secondary palette
|
||
|
contains the two colours used to render the fill pattern. For example, to draw a
|
||
|
white and red (7 and 8) checkerboard pattern for only blue pixels (colour 12) in a
|
||
|
sprite:
|
||
|
|
||
|
FOR I=0,15 DO PAL(I, I+I*16, 2) END -- all other colours map to themselves
|
||
|
PAL(12, 0x87, 2) -- remap colour 12 in the secondary palette
|
||
|
|
||
|
FILLP(0b0011001111001100.01) -- checkerboard palette, applied to sprites
|
||
|
SPR(1, 64,64) -- draw the sprite
|
||
|
|
||
|
0b0.001 Apply Secondary Palette Globally
|
||
|
|
||
|
When set, the secondary palette mapping is also applied by all draw functions that
|
||
|
respect fill patterns (circfill, line etc). This can be useful when used in
|
||
|
conjunction with sprite drawing functions, so that the colour index of each sprite
|
||
|
pixel means the same thing as the colour index supplied to the drawing functions.
|
||
|
|
||
|
FILLP(0b0011001111001100.001)
|
||
|
PAL(12, 0x87, 2)
|
||
|
CIRCFILL(64,64,20,12) -- red and white checkerboard circle
|
||
|
|
||
|
The secondary palette mapping is applied after the regular draw palette mapping. So
|
||
|
the following would also draw a red and white checkered circle:
|
||
|
|
||
|
PAL(3,12)
|
||
|
CIRCFILL(64,64,20,3)
|
||
|
|
||
|
The fill pattern can also be set by setting bits in any colour parameter (for example, the
|
||
|
parameter to @COLOR(), or the last parameter to @LINE(), @RECT() etc.
|
||
|
|
||
|
POKE(0x5F34, 1) -- sets integrated fillpattern + colour mode
|
||
|
CIRCFILL(64,64,20, 0x114E.ABCD) -- sets fill pattern to ABCD
|
||
|
|
||
|
When using the colour parameter to set the fill pattern, the following bits are used:
|
||
|
|
||
|
bit 0x1000.0000 means the non-colour bits should be observed
|
||
|
bit 0x0100.0000 transparency
|
||
|
bit 0x0200.0000 apply to sprites
|
||
|
bit 0x0400.0000 apply secondary palette
|
||
|
bits 0x00FF.0000 are the usual colour bits
|
||
|
bits 0x0000.FFFF are interpreted as the fill pattern
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
Table Functions
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
With the exception of PAIRS(), the following functions and the # operator apply only to tables
|
||
|
that are indexed starting from 1 and do not have NIL entries. All other forms of tables can be
|
||
|
considered as hash maps or sets, rather than arrays that have a length.
|
||
|
|
||
|
|
||
|
ADD(TBL, VAL, [INDEX])
|
||
|
|
||
|
Add value VAL to the end of table TBL. Equivalent to:
|
||
|
|
||
|
TBL[#TBL + 1] = VAL
|
||
|
|
||
|
If index is given then the element is inserted at that position:
|
||
|
|
||
|
FOO={} -- CREATE EMPTY TABLE
|
||
|
ADD(FOO, 11)
|
||
|
ADD(FOO, 22)
|
||
|
PRINT(FOO[2]) -- 22
|
||
|
|
||
|
|
||
|
DEL(TBL, VAL)
|
||
|
|
||
|
Delete the first instance of value VAL in table TBL. The remaining entries are shifted left
|
||
|
one index to avoid holes.
|
||
|
|
||
|
Note that VAL is the value of the item to be deleted, not the index into the table. (To
|
||
|
remove an item at a particular index, use DELI instead). DEL returns the deleted item, or
|
||
|
returns no value when nothing was deleted.
|
||
|
|
||
|
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
|
||
|
|
||
|
|
||
|
DELI(TBL, [I])
|
||
|
|
||
|
Like @DEL(), but remove the item from table TBL at index I When I is not given, the last
|
||
|
element of the table is removed and returned.
|
||
|
|
||
|
|
||
|
COUNT(TBL, [VAL])
|
||
|
|
||
|
Returns the length of table t (same as #TBL) When VAL is given, returns the number of
|
||
|
instances of VAL in that table.
|
||
|
|
||
|
|
||
|
ALL(TBL)
|
||
|
|
||
|
Used in FOR loops to iterate over all items in a table (that have a 1-based integer index),
|
||
|
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(TBL, FUNC)
|
||
|
|
||
|
For each item in table TBL, call function FUNC with the item as a single parameter.
|
||
|
|
||
|
> FOREACH({1,2,3}, PRINT)
|
||
|
|
||
|
|
||
|
PAIRS(TBL)
|
||
|
|
||
|
Used in FOR loops to iterate over table TBL, 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([B], [PL])
|
||
|
|
||
|
Get button B state for player PL (default 0)
|
||
|
|
||
|
B: 0..5: left right up down button_o button_x<br> PL: player index 0..7
|
||
|
|
||
|
Instead of using a number for B, it is also possible to use a button glyph. (In the coded
|
||
|
editor, use Shift-L R U D O X)
|
||
|
|
||
|
If no parameters supplied, returns a bitfield of all 12 button states for player 0 & 1 //
|
||
|
P0: bits 0..5 P1: bits 8..13
|
||
|
|
||
|
Default keyboard mappings to player buttons:
|
||
|
|
||
|
player 0: [DPAD]: cursors, [O]: Z C N [X]: X V M
|
||
|
player 1: [DPAD]: SFED, [O]: LSHIFT [X]: TAB W Q A
|
||
|
|
||
|
Although PICO-8 accepts all button combinations, note that it is generally impossible to
|
||
|
press both LEFT and RIGHT at the same time on a physical game controller. On some
|
||
|
controllers, UP + LEFT/RIGHT is also awkward if [X] or [O] could be used instead of UP
|
||
|
(e.g. to jump / accelerate).
|
||
|
|
||
|
|
||
|
BTNP(B, [PL])
|
||
|
|
||
|
BTNP is short for "Button Pressed"; Instead of being true when a button is held down, BTNP
|
||
|
returns true when a button is down AND it was not down the last frame. It also repeats
|
||
|
after 15 frames, returning true every 4 frames after that (at 30fps -- double that at
|
||
|
60fps). This can be used for things like menu navigation or grid-wise player movement.
|
||
|
|
||
|
The state that BTNP reads is reset at the start of each call to @_UPDATE or @_UPDATE60, so
|
||
|
it is preferable to use BTNP from inside one of those functions.
|
||
|
|
||
|
Custom delays (in frames @ 30fps) can be set by poking the following memory addresses:
|
||
|
|
||
|
POKE(0X5F5C, DELAY) -- SET THE INITIAL DELAY BEFORE REPEATING. 255 MEANS NEVER REPEAT.
|
||
|
POKE(0X5F5D, DELAY) -- SET THE REPEATING DELAY.
|
||
|
|
||
|
In both cases, 0 can be used for the default behaviour (delays 15 and 4)
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
Audio
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
SFX(N, [CHANNEL], [OFFSET], [LENGTH])
|
||
|
|
||
|
Play sfx N (0..63) on CHANNEL (0..3) from note OFFSET (0..31 in notes) for LENGTH notes.
|
||
|
|
||
|
Using negative CHANNEL values have special meanings:
|
||
|
|
||
|
CHANNEL -1: (default) to automatically choose a channel that is not being used
|
||
|
CHANNEL -2: to stop the given sound from playing on any channel
|
||
|
|
||
|
N can be a command for the given CHANNEL (or all channels when CHANNEL < 0):
|
||
|
|
||
|
N -1: to stop sound on that channel
|
||
|
N -2: to release sound on that channel from looping
|
||
|
|
||
|
SFX(3) -- PLAY SFX 3
|
||
|
SFX(3,2) -- PLAY SFX 3 ON CHANNEL 2
|
||
|
SFX(3,-2) -- STOP SFX 3 FROM PLAYING ON ANY CHANNEL
|
||
|
SFX(-1,2) -- STOP WHATEVER IS PLAYING ON CHANNEL 2
|
||
|
SFX(-2,2) -- RELEASE LOOPING ON CHANNEL 2
|
||
|
SFX(-1) -- STOP ALL SOUNDS ON ALL CHANNELS
|
||
|
SFX(-2) -- RELEASE LOOPING ON ALL CHANNELS
|
||
|
|
||
|
|
||
|
MUSIC(N, [FADE_LEN], [CHANNEL_MASK])
|
||
|
|
||
|
Play music starting from pattern N (0..63)
|
||
|
N -1 to stop music
|
||
|
|
||
|
FADE_LEN is in ms (default: 0). So to fade pattern 0 in over 1 second:
|
||
|
|
||
|
MUSIC(0, 1000)
|
||
|
|
||
|
CHANNEL_MASK specifies which channels to reserve for music only. For example, to play only
|
||
|
on channels 0..2:
|
||
|
|
||
|
MUSIC(0, NIL, 7) -- 1 | 2 | 4
|
||
|
|
||
|
Reserved channels can still be used to play sound effects on, but only when that channel
|
||
|
index is explicitly requested by @SFX().
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
Map
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
The PICO-8 map is a 128x32 grid of 8-bit values, or 128x64 when using the shared memory. When
|
||
|
using the map editor, the meaning of each value is taken to be an index into the sprite sheet
|
||
|
(0..255). However, it can instead be used as a general block of data.
|
||
|
|
||
|
|
||
|
MGET(X, Y)
|
||
|
|
||
|
MSET(X, Y, VAL)
|
||
|
|
||
|
Get or set map value (VAL) at X,Y
|
||
|
|
||
|
When X and Y are out of bounds, MGET returns 0, or a custom return value that can be
|
||
|
specified with:
|
||
|
|
||
|
POKE(0x5f36, 0x10)
|
||
|
POKE(0x5f5a, NEWVAL)
|
||
|
|
||
|
|
||
|
MAP(TILE_X, TILE_Y, [SX, SY], [TILE_W, TILE_H], [LAYERS])
|
||
|
|
||
|
Draw section of map (starting from TILE_X, TILE_Y) at screen position SX, SY (pixels).
|
||
|
|
||
|
To draw a 4x2 blocks of tiles starting from 0,0 in the map, to the screen at 20,20:
|
||
|
|
||
|
MAP(0, 0, 20, 20, 4, 2)
|
||
|
|
||
|
TILE_W and TILE_H default to the entire map (including shared space when applicable).
|
||
|
|
||
|
MAP() is often used in conjunction with CAMERA(). To draw the map so that a player object
|
||
|
(at PL.X in PL.Y in pixels) is centered:
|
||
|
|
||
|
CAMERA(PL.X - 64, PL.Y - 64)
|
||
|
MAP()
|
||
|
|
||
|
LAYERS is a bitfield. When given, only sprites with matching sprite flags are drawn. For
|
||
|
example, when LAYERS is 0x5, only sprites with flag 0 and 2 are drawn.
|
||
|
|
||
|
Sprite 0 is taken to mean "empty" and is not drawn. To disable this behaviour, use:
|
||
|
POKE(0x5F36, 0x8)
|
||
|
|
||
|
|
||
|
TLINE(X0, Y0, X1, Y1, MX, MY, [MDX, MDY], [LAYERS])
|
||
|
|
||
|
Draw a textured line from (X0,Y0) to (X1,Y1), sampling colour values from the map. When
|
||
|
LAYERS is specified, only sprites with matching flags are drawn (similar to MAP())
|
||
|
|
||
|
MX, MY are map coordinates to sample from, given in tiles. Colour values are sampled from
|
||
|
the 8x8 sprite present at each map tile. For example:
|
||
|
|
||
|
2.0, 1.0 means the top left corner of the sprite at position 2,1 on the map
|
||
|
2.5, 1.5 means pixel (4,4) of the same sprite
|
||
|
|
||
|
MDX, MDY are deltas added to mx, my after each pixel is drawn. (Defaults to 0.125, 0)
|
||
|
|
||
|
The map coordinates (MX, MY) are masked by values calculated by subtracting 0x0.0001 from
|
||
|
the values at address 0x5F38 and 0x5F39. In simpler terms, this means you can loop a
|
||
|
section of the map by poking the width and height you want to loop within, as long as they
|
||
|
are powers of 2 (2,4,8,16..)
|
||
|
|
||
|
For example, to loop every 8 tiles horizontally, and every 4 tiles vertically:
|
||
|
|
||
|
POKE(0x5F38, 8)
|
||
|
POKE(0x5F39, 4)
|
||
|
TLINE(...)
|
||
|
|
||
|
The default values (0,0) gives a masks of 0xff.ffff, which means that the samples will loop
|
||
|
every 256 tiles.
|
||
|
|
||
|
An offset to sample from (also in tiles) can also be specified at addresses 0x5f3a, 0x5f3b:
|
||
|
|
||
|
POKE(0x5F3A, OFFSET_X)
|
||
|
POKE(0x5F3B, OFFSET_Y)
|
||
|
|
||
|
Sprite 0 is taken to mean "empty" and not drawn. To disable this behaviour, use:
|
||
|
POKE(0x5F36, 0x8)
|
||
|
|
||
|
:: Setting TLINE Precision
|
||
|
|
||
|
By default, tline coordinates (mx,my,mdx,mdy) are expressed in tiles. This means that 1
|
||
|
pixel is 0.125, and only 13 bits are used for the fractional part. If more precision is
|
||
|
needed, the coordinate space can be adjusted to allow more bits for the fractional part.
|
||
|
This can be useful for things like textured walls, where the accumulated error from mdx,mdy
|
||
|
rounding maybe become visible when viewed up close.
|
||
|
|
||
|
The number of bits used for the fractional part of each pixel is stored in a special
|
||
|
register that can be adjusted by calling TLINE once with a single argument:
|
||
|
|
||
|
TLINE(16) -- MX,MY,MDX,MDY expressed in pixels
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
Memory
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
PICO-8 has 3 types of memory:
|
||
|
|
||
|
1. Base RAM (64k): see layout below. Access with PEEK() POKE() MEMCPY() MEMSET()
|
||
|
2. Cart ROM (32k): same layout as base ram until 0x4300
|
||
|
3. Lua RAM (2MB): compiled program + variables
|
||
|
|
||
|
Technical note: 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 (i.e. calls @RELOAD()) in 3 cases:<br> 1. When a cartridge is
|
||
|
loaded<br> 2. When a cartridge is run<br> 3. When exiting any of the editor modes // can
|
||
|
turn off with: poke(0x5f37,1)<br>
|
||
|
|
||
|
:: Base RAM Memory Layout
|
||
|
|
||
|
0X0 GFX
|
||
|
0X1000 GFX2/MAP2 (SHARED)
|
||
|
0X2000 MAP
|
||
|
0X3000 GFX FLAGS
|
||
|
0X3100 SONG
|
||
|
0X3200 SFX
|
||
|
0X4300 USER DATA
|
||
|
0X5600 CUSTOM FONT (IF ONE IS DEFINED)
|
||
|
0X5E00 PERSISTENT CART DATA (256 BYTES)
|
||
|
0X5F00 DRAW STATE
|
||
|
0X5F40 HARDWARE STATE
|
||
|
0X5F80 GPIO PINS (128 BYTES)
|
||
|
0X6000 SCREEN (8K)
|
||
|
0x8000 USER DATA
|
||
|
|
||
|
User data has no particular meaning and can be used for anything via @MEMCPY(), @PEEK() &
|
||
|
@POKE(). Persistent cart data is mapped to 0x5e00..0x5eff but only stored if @CARTDATA()
|
||
|
has been called. Colour format (gfx/screen) is 2 pixels per byte: low bits encode the left
|
||
|
pixel of each pair. Map format is one byte per tile, where each byte normally encodes a
|
||
|
sprite index.
|
||
|
|
||
|
:: Remapping Graphics and Map Data
|
||
|
|
||
|
The GFX, MAP and SCREEN memory areas can be reassigned by setting values at the following
|
||
|
addresses:
|
||
|
|
||
|
0X5F54 GFX: can be 0x00 (default) or 0x60 (use the screen memory as the spritesheet)
|
||
|
0X5F55 SCREEN: can be 0x60 (default) or 0x00 (use the spritesheet as screen memory)
|
||
|
0X5F56 MAP: can be 0x20 (default) or 0x10..0x2f, or 0x80 and above.
|
||
|
0X5F57 MAP SIZE: map width. 0 means 256. Defaults to 128.
|
||
|
|
||
|
Addresses can be expressed in 256 byte increments. So 0x20 means 0x2000, 0x21 means 0x2100
|
||
|
etc. Map addresses 0x30..0x3f are taken to mean 0x10..0x1f (shared memory area). Map data
|
||
|
can only be contained inside the memory regions 0x1000..0x2fff, 0x8000..0xffff, and the
|
||
|
map height is determined to be the largest possible size that fits in the given region.
|
||
|
|
||
|
GFX and SCREEN memory mapping happens at a low level which also affects memory access
|
||
|
functions (peek, poke, memcpy). The 8k memory blocks starting at 0x0 and 0x6000 can be
|
||
|
thought of as pointers to a separate video ram, and settings the values at 0X5F54 and
|
||
|
0X5F56 alters those pointers.
|
||
|
|
||
|
|
||
|
PEEK(ADDR, [N])
|
||
|
|
||
|
Read a byte from an address in base ram. If N is specified, PEEK() returns that number of
|
||
|
results (max: 8192). For example, to read the first 2 bytes of video memory:
|
||
|
|
||
|
A, B = PEEK(0x6000, 2)
|
||
|
|
||
|
|
||
|
POKE(ADDR, VAL1, VAL2, ...)
|
||
|
|
||
|
Write one or more bytes to an address in base ram. If more than one parameter is provided,
|
||
|
they are written sequentially (max: 8192).
|
||
|
|
||
|
|
||
|
PEEK2(ADDR)
|
||
|
|
||
|
POKE2(ADDR, VAL)
|
||
|
|
||
|
PEEK4(ADDR)
|
||
|
|
||
|
POKE4(ADDR, VAL)
|
||
|
|
||
|
16-bit and 32-bit versions of PEEK and POKE. Read and write one number (VAL) in
|
||
|
little-endian format:
|
||
|
|
||
|
16 bit: 0xffff.0000
|
||
|
32 bit: 0xffff.ffff
|
||
|
|
||
|
ADDR does not need to be aligned to 2 or 4-byte boundaries.
|
||
|
|
||
|
Alternatively, the following operators can be used to peek (but not poke), and are slightly
|
||
|
faster:
|
||
|
|
||
|
@ADDR -- PEEK(ADDR)
|
||
|
%ADDR -- PEEK2(ADDR)
|
||
|
$ADDR -- PEEK4(ADDR)
|
||
|
|
||
|
|
||
|
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, [FILENAME])
|
||
|
|
||
|
Same as MEMCPY, but copies from cart rom.
|
||
|
|
||
|
The code section ( >= 0x4300) is protected and can not be read.
|
||
|
|
||
|
If filename specified, load data from a separate cartridge. In this case, the cartridge
|
||
|
must be local (BBS carts can not be read in this way).
|
||
|
|
||
|
|
||
|
CSTORE(DEST_ADDR, SOURCE_ADDR, LEN, [FILENAME])
|
||
|
|
||
|
Same as memcpy, but copies from base ram to cart rom.
|
||
|
|
||
|
CSTORE() is equivalent to CSTORE(0, 0, 0x4300)
|
||
|
|
||
|
The code section ( >= 0x4300) is protected and can not be written to.
|
||
|
|
||
|
If FILENAME is specified, the data is written directly to that cartridge on disk. Up to 64
|
||
|
cartridges can be written in one session. See @{Cartridge Data} for more information.
|
||
|
|
||
|
|
||
|
MEMSET(DEST_ADDR, VAL, LEN)
|
||
|
|
||
|
Write the 8-bit value VAL into memory starting at DEST_ADDR, for LEN bytes.
|
||
|
|
||
|
For example, to fill half of video memory with 0xC8:
|
||
|
|
||
|
> MEMSET(0x6000, 0xC8, 0x1000)
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
Math
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
MAX(X, Y)
|
||
|
|
||
|
MIN(X, Y)
|
||
|
|
||
|
MID(X, Y, Z)
|
||
|
|
||
|
Returns the maximum, minimum, or middle value of parameters
|
||
|
|
||
|
> ?MID(7,5,10) -- 7
|
||
|
|
||
|
|
||
|
FLR(X)
|
||
|
|
||
|
> ?FLR ( 4.1) --> 4
|
||
|
> ?FLR (-2.3) --> -3
|
||
|
|
||
|
|
||
|
CEIL(X)
|
||
|
|
||
|
Returns the closest integer that is equal to or below x
|
||
|
|
||
|
> ?CEIL( 4.1) --> 5
|
||
|
> ?CEIL(-2.3) --> -2
|
||
|
|
||
|
|
||
|
COS(X)
|
||
|
|
||
|
SIN(X)
|
||
|
|
||
|
Returns the cosine or sine of x, where 1.0 means a full turn. For example, to animate a
|
||
|
dial that turns once every second:
|
||
|
|
||
|
FUNCTION _DRAW()
|
||
|
CLS()
|
||
|
CIRC(64, 64, 20, 7)
|
||
|
X = 64 + COS(T()) * 20
|
||
|
Y = 64 + SIN(T()) * 20
|
||
|
LINE(64, 64, X, Y)
|
||
|
END
|
||
|
|
||
|
PICO-8's SIN() returns an inverted result to suit screenspace (where Y means "DOWN", as
|
||
|
opposed to mathematical diagrams where Y typically means "UP").
|
||
|
|
||
|
> SIN(0.25) -- RETURNS -1
|
||
|
|
||
|
To get conventional radian-based trig functions without the y inversion, paste the
|
||
|
following snippet near the start of your program:
|
||
|
|
||
|
P8COS = COS FUNCTION COS(ANGLE) RETURN P8COS(ANGLE/(3.1415*2)) END
|
||
|
P8SIN = SIN FUNCTION SIN(ANGLE) RETURN -P8SIN(ANGLE/(3.1415*2)) END
|
||
|
|
||
|
|
||
|
ATAN2(DX, DY)
|
||
|
|
||
|
Converts DX, DY into an angle from 0..1
|
||
|
|
||
|
As with cos/sin, angle is taken to run anticlockwise in screenspace. For example:
|
||
|
|
||
|
> ?ATAN(0, -1) -- RETURNS 0.25
|
||
|
|
||
|
ATAN2 can be used to find the direction between two points:
|
||
|
|
||
|
X=20 Y=30
|
||
|
FUNCTION _UPDATE()
|
||
|
IF (BTN(0)) X-=2
|
||
|
IF (BTN(1)) X+=2
|
||
|
IF (BTN(2)) Y-=2
|
||
|
IF (BTN(3)) Y+=2
|
||
|
END
|
||
|
|
||
|
FUNCTION _DRAW()
|
||
|
CLS()
|
||
|
CIRCFILL(X,Y,2,14)
|
||
|
CIRCFILL(64,64,2,7)
|
||
|
|
||
|
A=ATAN2(X-64, Y-64)
|
||
|
PRINT("ANGLE: "..A)
|
||
|
LINE(64,64,
|
||
|
64+COS(A)*10,
|
||
|
64+SIN(A)*10,7)
|
||
|
END
|
||
|
|
||
|
|
||
|
SQRT(X)
|
||
|
|
||
|
Return the square root of x
|
||
|
|
||
|
|
||
|
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)). If x is an array-style table, return a random
|
||
|
element between table[1] and table[#table].
|
||
|
|
||
|
|
||
|
SRAND(X)
|
||
|
|
||
|
Sets the random number seed. The seed is automatically randomized on cart startup.
|
||
|
|
||
|
FUNCTION _DRAW()
|
||
|
CLS()
|
||
|
SRAND(33)
|
||
|
FOR I=1,100 DO
|
||
|
PSET(RND(128),RND(128),7)
|
||
|
END
|
||
|
END
|
||
|
|
||
|
:: Bitwise Operations
|
||
|
|
||
|
Bitwise operations are similar to logical expressions, except that they work at the bit
|
||
|
level.
|
||
|
|
||
|
Say you have two numbers (written here in binary using the "0b" prefix):
|
||
|
|
||
|
X = 0b1010
|
||
|
Y = 0b0110
|
||
|
|
||
|
A bitwise AND will give you bits set when the corresponding bits in X /and/ Y are both set
|
||
|
|
||
|
> PRINT(BAND(X,Y)) -- RESULT:0B0010 (2 IN DECIMAL)
|
||
|
|
||
|
There are 9 bitwise functions available in PICO-8:
|
||
|
|
||
|
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
|
||
|
|
||
|
Operator versions are also available: & | ^^ ~ << >> >>> <<> >><
|
||
|
|
||
|
For example: PRINT(67 & 63) -- result:3 equivalent to BAND(67,63)
|
||
|
|
||
|
Operators are slightly faster than their corresponding functions. They behave exactly the
|
||
|
same, except that if any operands are not numbers the result is a runtime error (the
|
||
|
function versions instead default to a value of 0).
|
||
|
|
||
|
:: Integer Division
|
||
|
|
||
|
Integer division can be performed with a \
|
||
|
|
||
|
> PRINT(9\2) -- RESULT:4 EQUIVALENT TO FLR(9/2)
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
Custom Menu Items
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
MENUITEM(INDEX, [LABEL], [CALLBACK])
|
||
|
|
||
|
Add an extra item to the pause menu
|
||
|
|
||
|
Index should be 1..5 and determines the order each menu item is displayed label should be a
|
||
|
string up to 16 characters long callback is a function called when the item is selected by
|
||
|
the users
|
||
|
|
||
|
When no label or function is supplied, the menu item is removed
|
||
|
|
||
|
MENUITEM(1, "RESTART PUZZLE",
|
||
|
FUNCTION() RESET_PUZZLE() SFX(10) END
|
||
|
)
|
||
|
|
||
|
If the callback returns true, the pause menu remains open. The callback takes a single
|
||
|
parameter that is a bitfield of L,R,X button presses
|
||
|
|
||
|
MENUITEM(1, "FOO",
|
||
|
FUNCTION(B) IF (B&1 > 0) THEN PRINTH("LEFT WAS PRESSED") END END
|
||
|
)
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
Strings and Type Conversion
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
Strings in Lua are written either in single or double quotes or with matching [[ ]] brackets:
|
||
|
|
||
|
S = "THE QUICK"
|
||
|
S = 'BROWN FOX';
|
||
|
S = [[
|
||
|
JUMPS OVER
|
||
|
MULTIPLE LINES
|
||
|
]]
|
||
|
|
||
|
The length of a string (number of characters) can be retrieved using the # operator:
|
||
|
|
||
|
>PRINT(#S)
|
||
|
|
||
|
Strings can be joined using the .. operator. Joining numbers converts them to strings.
|
||
|
|
||
|
>PRINT("THREE "..4) --> "THREE 4"
|
||
|
|
||
|
When used as part of an arithmetic expression, string values are converted to numbers:
|
||
|
|
||
|
>PRINT(2+"3") --> 5
|
||
|
|
||
|
|
||
|
TOSTR(VAL, [FORMAT_FLAGS])
|
||
|
|
||
|
Convert VAL to a string.
|
||
|
|
||
|
FORMAT_FLAGS is a bitfield:
|
||
|
|
||
|
0x1: Write the raw hexadecimal value of numbers, functions or tables.
|
||
|
0x2: Write VAL as a signed 32-bit integer by shifting it left by 16 bits.
|
||
|
|
||
|
TOSTR(NIL) returns "[nil]"
|
||
|
|
||
|
TOSTR() returns ""
|
||
|
|
||
|
TOSTR(17) -- "17"
|
||
|
TOSTR(17,0x1) -- "0x0011.0000"
|
||
|
TOSTR(17,0x3) -- "0x00110000"
|
||
|
TOSTR(17,0x2) -- "1114112"
|
||
|
|
||
|
|
||
|
TONUM(VAL, [FORMAT_FLAGS])
|
||
|
|
||
|
Converts VAL to a number.
|
||
|
|
||
|
TONUM("17.5") -- 17.5
|
||
|
TONUM(17.5) -- 17.5
|
||
|
TONUM("HOGE") -- NO RETURN VALUE
|
||
|
|
||
|
FORMAT_FLAGS is a bitfield:
|
||
|
|
||
|
0x1: Read the string as written in (unsigned, integer) hexadecimal without the "0x" prefix
|
||
|
Non-hexadecimal characters are taken to be '0'.
|
||
|
0x2: Read the string as a signed 32-bit integer, and shift right 16 bits.
|
||
|
0x4: When VAL can not be converted to a number, return 0
|
||
|
|
||
|
TONUM("FF", 0x1) -- 255
|
||
|
TONUM("1114112", 0x2) -- 17
|
||
|
TONUM("1234abcd", 0x3) -- 0x1234.abcd
|
||
|
|
||
|
|
||
|
CHR(VAL0, VAL1, ...)
|
||
|
|
||
|
Convert one or more ordinal character codes to a string.
|
||
|
|
||
|
When
|
||
|
|
||
|
CHR(64) -- "@"
|
||
|
CHR(104,101,108,108,111) -- "hello"
|
||
|
|
||
|
|
||
|
ORD(STR, [INDEX], [NUM_RESULTS])
|
||
|
|
||
|
Convert one or more characters from string STR to their ordinal (0..255) character codes.
|
||
|
|
||
|
Use the INDEX parameter to specify which character in the string to use. When INDEX is out
|
||
|
of range or str is not a string, ORD returns nil.
|
||
|
|
||
|
When NUM_RESULTS is given, ORD returns multiple values starting from INDEX.
|
||
|
|
||
|
ORD("@") -- 64
|
||
|
ORD("123",2) -- 50 (THE SECOND CHARACTER: "2")
|
||
|
ORD("123",2,3) -- 50,51,52
|
||
|
|
||
|
|
||
|
SUB(STR, POS0, [POS1])
|
||
|
|
||
|
Grab a substring from string str, from pos0 up to and including pos1. When POS1 is not
|
||
|
specified, the remainder of the string is returned. When POS1 is specified, but not a
|
||
|
number, a single character at POS0 is returned.
|
||
|
|
||
|
S = "THE QUICK BROWN FOX"
|
||
|
PRINT(SUB(S,5,9)) --> "QUICK"
|
||
|
PRINT(SUB(S,5)) --> "QUICK BROWN FOX"
|
||
|
PRINT(SUB(S,5,_)) --> "Q"
|
||
|
|
||
|
|
||
|
SPLIT(STR, [SEPARATOR], [CONVERT_NUMBERS])
|
||
|
|
||
|
Split a string into a table of elements delimited by the given separator (defaults to ",").
|
||
|
When separator is a number n, the string is split into n-character groups. When
|
||
|
convert_numbers is true, numerical tokens are stored as numbers (defaults to true). Empty
|
||
|
elements are stored as empty strings.
|
||
|
|
||
|
SPLIT("1,2,3") -- {1,2,3}
|
||
|
SPLIT("ONE:TWO:3",":",FALSE) -- {"ONE","TWO","3"}
|
||
|
SPLIT("1,,2,") -- {1,"",2,""}
|
||
|
|
||
|
|
||
|
TYPE(VAL)
|
||
|
|
||
|
Returns the type of val as a string.
|
||
|
|
||
|
> PRINT(TYPE(3))
|
||
|
NUMBER
|
||
|
> PRINT(TYPE("3"))
|
||
|
STRING
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
Cartridge Data
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
Using @CARTDATA(), @DSET(), AND @DGET(), 64 numbers (256 bytes) of persistent data can be
|
||
|
stored on the user's PICO-8 that persists after the cart is unloaded or PICO-8 is shutdown.
|
||
|
This can be used as a lightweight way to store things like high scores or to save player
|
||
|
progress. It can also be used to share data across cartridges / cartridge versions.
|
||
|
|
||
|
If more than 256 bytes is needed, it is also possible to write directly to the cartridge using
|
||
|
@CSTORE(). The disadvantage is that the data is tied to that particular version of the
|
||
|
cartridge. e.g. if a game is updated, players will lose their savegames. Also, some space in
|
||
|
the data sections of the cartridge need to be left available to use as storage.
|
||
|
|
||
|
Another alternative is to write directly to a second cartridge by specifying a fourth parameter
|
||
|
to @CSTORE(). This requires a cart swap (which in reality only means the user needs to watch a
|
||
|
spinny cart animation for 1 second).
|
||
|
|
||
|
CSTORE(0,0,0X2000, "SPRITE SHEET.P8")
|
||
|
-- LATER, RESTORE THE SAVED DATA:
|
||
|
RELOAD(0,0,0X2000, "SPRITE SHEET.P8")
|
||
|
|
||
|
|
||
|
CARTDATA(ID)
|
||
|
|
||
|
Opens a permanent data storage slot indexed by ID that can be used to store and retrieve up
|
||
|
to 256 bytes (64 numbers) worth of data using @DSET() and @DGET().
|
||
|
|
||
|
CARTDATA("ZEP_DARK_FOREST")
|
||
|
DSET(0, SCORE)
|
||
|
|
||
|
ID is a string up to 64 characters long, and should be unusual enough that other
|
||
|
cartridges do not accidentally use the same id. Legal characters are a..z, 0..9 and
|
||
|
underscore (_)
|
||
|
|
||
|
Returns true if data was loaded, otherwise false.
|
||
|
|
||
|
CARTDATA can be called once per cartridge execution, and so only a single data slot can be
|
||
|
used.
|
||
|
|
||
|
Once a cartdata ID has been set, the area of memory 0X5E00..0X5EFF is mapped to permanent
|
||
|
storage, and can either be accessed directly or via @DGET()/@DSET().
|
||
|
|
||
|
There is no need to flush written data -- it is automatically saved to permanent storage
|
||
|
even if modified by directly @POKE()'ing 0X5E00..0X5EFF.
|
||
|
|
||
|
|
||
|
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()
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
GPIO
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
GPIO stands for "General Purpose Input Output", and allows machines to communicate with each
|
||
|
other. PICO-8 maps bytes in the range 0x5f80..0x5fff to gpio pins that can be
|
||
|
|
||
|
|
||
|
POKE()ed (to output a value -- e.g. to make an LED light up) or @PEEK()ed (e.g. to read
|
||
|
|
||
|
the state of a switch).
|
||
|
|
||
|
GPIO means different things for different host platforms:
|
||
|
|
||
|
CHIP: 0x5f80..0x5f87 mapped to xio-p0..xio-p7
|
||
|
Pocket CHIP: 0x5f82..0x5f87 mapped to GPIO1..GPIO6
|
||
|
// xio-p0 & p1 are exposed inside the prototyping area inside the case.
|
||
|
Raspberry Pi: 0x5f80..0x5f9f mapped to wiringPi pins 0..31
|
||
|
// see http://wiringpi.com/pins/ for mappings on different models.
|
||
|
// also: watch out for BCM vs. WiringPi GPIO indexing!
|
||
|
|
||
|
CHIP and Raspberry Pi values are all digital: 0 (LOW) and 255 (HIGH)
|
||
|
|
||
|
A program to blink any LEDs attached on and off:
|
||
|
|
||
|
T = 0
|
||
|
FUNCTION _DRAW()
|
||
|
CLS(5)
|
||
|
FOR I=0,7 DO
|
||
|
VAL = 0
|
||
|
IF (T % 2 < 1) VAL = 255
|
||
|
POKE(0X5F80 + I, VAL)
|
||
|
CIRCFILL(20+I*12,64,4,VAL/11)
|
||
|
END
|
||
|
T += 0.1
|
||
|
END
|
||
|
|
||
|
:: Serial
|
||
|
|
||
|
For more precise timing, the @SERIAL() command can be used. GPIO writes are buffered and
|
||
|
dispatched at the end of each frame, allowing clock cycling at higher and/or more regular
|
||
|
speeds than is possible by manually bit-banging using @POKE() calls.
|
||
|
|
||
|
|
||
|
SERIAL(CHANNEL, ADDRESS, LENGTH)
|
||
|
|
||
|
CHANNEL:
|
||
|
0x000..0x0fe corresponds to gpio pin numbers; send 0x00 for LOW or 0xFF for HIGH
|
||
|
0x0ff delay; length is taken to mean "duration" in microseconds (excl. overhead)
|
||
|
0x400..0x401 ws281x LED string (experimental)
|
||
|
|
||
|
ADDRESS: The PICO-8 memory location to read from / write to.
|
||
|
|
||
|
LENGTH: Number of bytes to send. 1/8ths are allowed to send partial bit strings.
|
||
|
|
||
|
For example, to send a byte one bit at a time to a typical APA102 LED string:
|
||
|
|
||
|
VAL = 42 -- VALUE TO SEND
|
||
|
DAT = 16 CLK = 15 -- DATA AND CLOCK PINS DEPEND ON DEVICE
|
||
|
POKE(0X4300,0) -- DATA TO SEND (SINGLE BYTES: 0 OR 0XFF)
|
||
|
POKE(0X4301,0XFF)
|
||
|
FOR B=0,7 DO
|
||
|
-- SEND THE BIT (HIGH FIRST)
|
||
|
SERIAL(DAT, BAND(VAL, SHL(1,7-B))>0 AND 0X4301 OR 0X4300, 1)
|
||
|
-- CYCLE THE CLOCK
|
||
|
SERIAL(CLK, 0X4301)
|
||
|
SERIAL(0XFF, 5) -- DELAY 5
|
||
|
SERIAL(CLK, 0X4300)
|
||
|
SERIAL(0XFF, 5) -- DELAY 5
|
||
|
END
|
||
|
|
||
|
Additional channels are available for bytestreams to and from the host operating system.
|
||
|
These are intended to be most useful for UNIX-like environments while developing
|
||
|
toolchains, and are not available while running a BBS or exported cart [1]. Maximum
|
||
|
transfer rate in all cases is 64k/sec (blocks cpu).
|
||
|
|
||
|
0x800 dropped file // stat(120) returns TRUE when data is available
|
||
|
0x802 dropped image // stat(121) returns TRUE when data is available
|
||
|
0x804 stdin
|
||
|
0x805 stdout
|
||
|
0x806 file specified with: pico8 -i filename
|
||
|
0x807 file specified with: pico8 -o filename
|
||
|
|
||
|
Image files dropped into PICO-8 show up on channel 0x802 as a bytestream with a special
|
||
|
format: The first 4 bytes are the image's width and height (2 bytes each little-endian,
|
||
|
like PEEK2), followed by the image in reading order, one byte per pixel, colour-fitted to
|
||
|
the display palette at the time the file was dropped.
|
||
|
|
||
|
[1] Channels 0x800 and 0x802 are available from exported binaries, but with a maximum file
|
||
|
size of 256k, or 128x128 for images.
|
||
|
|
||
|
:: HTML
|
||
|
|
||
|
Cartridges exported as HTML / .js use a global array of integers (pico8_gpio) to represent
|
||
|
gpio pins. The shell HTML should define the array:
|
||
|
|
||
|
var pico8_gpio = Array(128);
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
Mouse and Keyboard Input
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
// EXPERIMENTAL -- but mostly working on all platforms
|
||
|
|
||
|
Mouse and keyboard input can be achieved by enabling devkit input mode:
|
||
|
|
||
|
POKE(0x5F2D, flags) -- where flags are:
|
||
|
|
||
|
0x1 Enable
|
||
|
0x2 Mouse buttons trigger btn(4)..btn(6)
|
||
|
0x4 Pointer lock (use stat 38..39 to read movements)
|
||
|
|
||
|
Note that not every PICO-8 will have a keyboard or mouse attached to it, so when posting carts
|
||
|
to the Lexaloffle BBS, it is encouraged to make keyboard and/or mouse control optional and off
|
||
|
by default, if possible. When devkit input mode is enabled, a message is displayed to BBS users
|
||
|
warning them that the program may be expecting input beyond the standard 6-button controllers.
|
||
|
|
||
|
The state of the mouse and keyboard can be found in stat(x):
|
||
|
|
||
|
STAT(30) -- (Boolean) True when a keypress is available
|
||
|
STAT(31) -- (String) character returned by keyboard
|
||
|
STAT(32) -- Mouse X
|
||
|
STAT(33) -- Mouse Y
|
||
|
STAT(34) -- Mouse buttons (bitfield)
|
||
|
STAT(36) -- Mouse wheel event
|
||
|
STAT(38) -- Relative x movement (in host desktop pixels) -- requires flag 0x4
|
||
|
STAT(39) -- Relative y movement (in host desktop pixels) -- requires flag 0x4
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
Additional Lua Features
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
PICO-8 also exposes 2 features of Lua for advanced users: Metatables and Coroutines.
|
||
|
|
||
|
For more information, please refer to the Lua 5.2 manual.
|
||
|
|
||
|
:: Metatables
|
||
|
|
||
|
Metatables can be used to define the behaviour of objects under particular operations. For
|
||
|
example, to use tables to represent 2D vectors that can be added together, the '+' operator is
|
||
|
redefined by defining an "__add" function for the metatable:
|
||
|
|
||
|
VEC2D={
|
||
|
__ADD=FUNCTION(A,B)
|
||
|
RETURN {X=(A.X+B.X), Y=(A.Y+B.Y)}
|
||
|
END
|
||
|
}
|
||
|
|
||
|
V1={X=2,Y=9} SETMETATABLE(V1, VEC2D)
|
||
|
V2={X=1,Y=5} SETMETATABLE(V2, VEC2D)
|
||
|
V3 = V1+V2
|
||
|
PRINT(V3.X..","..V3.Y) -- 3,14
|
||
|
|
||
|
|
||
|
SETMETATABLE(TBL, M)
|
||
|
|
||
|
Set table TBL metatable to M
|
||
|
|
||
|
|
||
|
GETMETATABLE(TBL)
|
||
|
|
||
|
return the current metatable for table t, or nil if none is set
|
||
|
|
||
|
|
||
|
RAWSET(TBL, KEY, VALUE)
|
||
|
|
||
|
RAWGET(TBL, KEY)
|
||
|
|
||
|
RAWEQUAL(TBL1,TBL2
|
||
|
|
||
|
RAWLEN(TBL)
|
||
|
|
||
|
Raw access to the table, as if no metamethods were defined.
|
||
|
|
||
|
:: Function Arguments
|
||
|
|
||
|
The list of function arguments can be specifed with ...
|
||
|
|
||
|
FUNCTION PREPRINT(PRE, S, ...)
|
||
|
LOCAL S2 = PRE..TOSTR(S)
|
||
|
PRINT(S2, ...) -- PASS THE REMAINING ARGUMENTS ON TO PRINT()
|
||
|
END
|
||
|
|
||
|
To accept a variable number of arguments, use them to define a table and/or use Lua's select()
|
||
|
function. select(index, ...) returns all of the arguments after index.
|
||
|
|
||
|
FUNCTION FOO(...)
|
||
|
LOCAL ARGS={...} -- BECOMES A TABLE OF ARGUMENTS
|
||
|
FOREACH(ARGS, PRINT)
|
||
|
?SELECT("#",...) -- ALTERNATIVE WAY TO COUNT THE NUMBER OF ARGUMENTS
|
||
|
FOO2(SELECT(3,...)) -- PASS ARGUMENTS FROM 3 ONWARDS TO FOO2()
|
||
|
END
|
||
|
|
||
|
:: Coroutines
|
||
|
|
||
|
Coroutines offer a way to run different parts of a program in a somewhat concurrent way,
|
||
|
similar to threads. A function can be called as a coroutine, suspended with
|
||
|
|
||
|
|
||
|
YIELD() any number of times, and then resumed again at the same points.
|
||
|
|
||
|
FUNCTION HEY()
|
||
|
PRINT("DOING SOMETHING")
|
||
|
YIELD()
|
||
|
PRINT("DOING THE NEXT THING")
|
||
|
YIELD()
|
||
|
PRINT("FINISHED")
|
||
|
END
|
||
|
|
||
|
C = COCREATE(HEY)
|
||
|
FOR I=1,3 DO CORESUME(C) END
|
||
|
|
||
|
|
||
|
COCREATE(F)
|
||
|
|
||
|
Create a coroutine for function f.
|
||
|
|
||
|
|
||
|
CORESUME(C, [P0, P1 ..])
|
||
|
|
||
|
Run or continue the coroutine c. Parameters p0, p1.. are passed to the coroutine's
|
||
|
function.
|
||
|
|
||
|
Returns true if the coroutine completes without any errors Returns false, error_message if
|
||
|
there is an error.
|
||
|
|
||
|
** Runtime errors that occur inside coroutines do not cause the program to stop running. It
|
||
|
is a good idea to wrap CORESUME() inside an @ASSERT(). If the assert fails, it will print
|
||
|
the error message generated by coresume.
|
||
|
|
||
|
|
||
|
ASSERT(CORESUME(C))
|
||
|
|
||
|
|
||
|
COSTATUS(C)
|
||
|
|
||
|
Return the status of coroutine C as a string:
|
||
|
"running"
|
||
|
"suspended"
|
||
|
"dead"
|
||
|
|
||
|
|
||
|
YIELD
|
||
|
|
||
|
Suspend execution and return to the caller.
|
||
|
|
||
|
====================================================================================================
|
||
|
Appendix
|
||
|
====================================================================================================
|
||
|
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
Appendix A: P8SCII Control Codes
|
||
|
----------------------------------------------------------------------------------------------------
|
||
|
|
||
|
When printed with @PRINT(), some characters have a special meaning that can be used to alter
|
||
|
things like the cursor position and text rendering style. Control characters in PICO-8 are
|
||
|
CHR(0)..CHR(15) and can be written as an escaped sequence ("\n" for newline etc.)
|
||
|
|
||
|
Some of the control codes below take parameters which are written using a scheme that is a
|
||
|
superset of hexadecimal format. That is, '0'..'f' also mean 0..15. But characters after 'f' are
|
||
|
also accepted: 'g' means 16 and so on. Such parameters are written below as P0, P1.
|
||
|
|
||
|
For example, to print with a blue background ("\#c") and dark gray foreground ("\f5"):
|
||
|
|
||
|
PRINT("\#C\F5 BLUE ")
|
||
|
|
||
|
The only side-effects on the draw state are changes in cursor position and foreground color;
|
||
|
all other attributes are reset each time @PRINT() is called.
|
||
|
|
||
|
:: Control Codes
|
||
|
|
||
|
0 "\0" terminate printing
|
||
|
1 "\*" repeat next character P0 times. ?"\*3a" --> aaa
|
||
|
2 "\#" draw solid background with colour P0
|
||
|
3 "\-" shift cursor horizontally by P0-16 pixels
|
||
|
4 "\|" shift cursor vertically by P0-16 pixels
|
||
|
5 "\+" shift cursor by P0-16, P1-16 pixels
|
||
|
6 "\^" special command (see below)
|
||
|
7 "\a" audio (see below)
|
||
|
8 "\b" backspace
|
||
|
9 "\t" tab
|
||
|
a "\n" newline
|
||
|
b "\v" decorate previous character (see below)
|
||
|
c "\f" set foreground colour
|
||
|
d "\r" carriage return
|
||
|
e "\014" switch to font defined at 0x5600
|
||
|
f "\015" switch to default font
|
||
|
|
||
|
:: Special Commands
|
||
|
|
||
|
These commands all start with "\^" and take up to 2 parameters (P0, P1) For example, to
|
||
|
clear screen to dark blue: print("\^c1")
|
||
|
|
||
|
1..9 skip 1,2,4,8,16,32..256 frames
|
||
|
c cls to colour P0, set cursor to 0,0
|
||
|
d set delay to P0 frames for every character printed
|
||
|
g set cursor position to home
|
||
|
h set home to cursor position
|
||
|
j jump to absolute P0*4, P1*4 (in screen pixels)
|
||
|
r set rhs character wrap boundary to P0*4
|
||
|
s set tab stop width to P0 pixels (used by "\t")
|
||
|
x set character width (default: 4)
|
||
|
y set character height (default: 6)
|
||
|
|
||
|
:: Rendering mode options
|
||
|
|
||
|
// prefix these with "-" to disable: e.g. ?"\^i on \^-i off "
|
||
|
|
||
|
w wide mode: scales by 2x1
|
||
|
t tall mode: scales by 1x2
|
||
|
= stripey mode: when wide or tall, draw only even pixels
|
||
|
p pinball mode: equivalent to setting wide, tall and stripey
|
||
|
i invert
|
||
|
b border: toggle 1px padding on left and top // on by default
|
||
|
# solid background // off by default, but enabled automatically by \#
|
||
|
|
||
|
:: Raw memory writes
|
||
|
|
||
|
The following two commands take 4-character hex parameters:
|
||
|
|
||
|
@addrnnnn[binstr] poke nnnn bytes to address addr
|
||
|
!addr[binstr] poke all remaining characters to address addr
|
||
|
|
||
|
For example, to write 4 bytes to video memory halfway down the screen:
|
||
|
|
||
|
>?"\^@70000004xxxxhello"
|
||
|
|
||
|
:: One-off characters
|
||
|
|
||
|
Character data can be specified and printed in-line using \^. followed by 8 bytes of
|
||
|
raw binary data, or \^: followed by 8 2-digit hexadecimal values. The data format is
|
||
|
the same as custom fonts; each byte specifies a row of 1-bit pixel values, with the
|
||
|
low bit on the left.
|
||
|
|
||
|
\^.[8 chars of raw binary data]
|
||
|
\^:[16 chars of hexadecimal]
|
||
|
|
||
|
To print a cat:
|
||
|
|
||
|
> ?"\^:447cb67c3e7f0106"
|
||
|
|
||
|
:: Audio
|
||
|
|
||
|
? ?"\A" -- SINGLE BEEP ?"\A12" -- PLAY EXISTING DATA AT SFX 12
|
||
|
|
||
|
If an sfx index is not specified, a non-active sfx between 60..63 is selected
|
||
|
automatically. To fill the SFX with data before playback, the following commands can then
|
||
|
be appended.
|
||
|
|
||
|
1. (optional) SFX attributes must appear once at the start as they apply to the whole
|
||
|
sound:
|
||
|
|
||
|
s P0 set the sfx speed
|
||
|
l P0 P1 set the sfx loop start and end points
|
||
|
|
||
|
2. Note data:
|
||
|
|
||
|
Note are written as a..g, optionally followed by a sharp # or flat -, and octave
|
||
|
number.
|
||
|
|
||
|
PRINT "\ACE-G" -- MINOR TRIAD
|
||
|
|
||
|
Empty notes Can be written with a dot:
|
||
|
|
||
|
PRINT "\AC..E-..G" -- STACCATO MINOR TRIAD
|
||
|
|
||
|
Note attribute commands apply to following notes:
|
||
|
|
||
|
i P0 set the instrument (default: 5)
|
||
|
v P0 set the volume (default: 5)
|
||
|
x P0 set the effect (default: 0)
|
||
|
|
||
|
For example, to play a fast (speed 4), staccato (effect 5) arpeggio starting at C1:
|
||
|
|
||
|
PRINT "\AS4X5C1EGC2EGC3EGC4"
|
||
|
|
||
|
:: 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 acute 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 Font
|
||
|
|
||
|
A custom font can be defined at 0x5600, consisting of 8 bytes per character * 256
|
||
|
characters = 2048 bytes. Each character is an 8x8 bitfield (1 bit/pixel), where starting
|
||
|
from the top, each row is a single byte starting with 0x1 on the left.
|
||
|
|
||
|
The first 128 bytes (characters 0~15 are never drawn) describe attributes of the font:
|
||
|
|
||
|
0x5600 character width in pixels (can be more than 8, but only 8 pixels are drawn)
|
||
|
0x5601 character width for character 128 and above
|
||
|
0x5602 character height in pixels
|
||
|
0x5603 draw offset x
|
||
|
0x5604 draw offset y
|
||
|
0x5605 flags: 0x1 apply_size_adjustments 0x2: apply tabs relative to cursor home
|
||
|
0x5606 tab width in pixels (used only when alt font is drawn)
|
||
|
0x5607 unused
|
||
|
|
||
|
The remaining 120 bytes are used to adjust the width and vertical offset of characters
|
||
|
16..255. Each nibble (low nibbles first) describes the adjustments for one characters:
|
||
|
|
||
|
bits 0x7: adjust character width by 0,1,2,3,-4,-3,-2,-1
|
||
|
bit 0x8: when set, draw the character one pixel higher (useful for latin accents)
|
||
|
|
||
|
:: Default Attributes
|
||
|
|
||
|
Although attributes are reset every time @PRINT() is called, it is possible to set their
|
||
|
default values by writing to memory addresses 0x5f58..0x5f5b.
|
||
|
|
||
|
0x5f58 // bitfield
|
||
|
0x1 when set to 0x1, bits 1..7 are observed:
|
||
|
0x2 padding
|
||
|
0x4 wide
|
||
|
0x8 tall
|
||
|
0x10 solid background
|
||
|
0x20 invert
|
||
|
0x40 stripey (when wide or tall)
|
||
|
0x80 use custom font
|
||
|
|
||
|
// e.g. poke(0x5f58, 0x1 | 0x2 | 0x4 | 0x8 | 0x20 | 0x40) -- pinball everywhere
|
||
|
|
||
|
0x5f59 char_w (low nibble), char_h (high)
|
||
|
0x5f5a char_w2 (low nibble), tab_w (high)
|
||
|
0x5f5b offset_x (low nibble), offset_y (high)
|
||
|
|
||
|
// any nibbles equal to 0 are ignored
|
||
|
// tab_w (global tab width) values are mapped to 4..60
|
||
|
|
||
|
|
||
|
--------------------------------------------------------------------------------------------
|
||
|
PICO-8 VERSION HISTORY
|
||
|
--------------------------------------------------------------------------------------------
|
||
|
|
||
|
v0.2.5g
|
||
|
|
||
|
Fixed: tonum("123abc") returns 123 (should return nothing) // also breaks split(). regression in 0.2.5f
|
||
|
Fixed: draw_tabs not listed by CONFIG command
|
||
|
|
||
|
|
||
|
v0.2.5f
|
||
|
|
||
|
Added: CONFIG DRAW_TABS 1 to show tab characters in code editor (previously required editing config.txt)
|
||
|
Changed: tokenizer recognises long comments / string using [=*[ ]=*] e.g. [==[ long string ]==]
|
||
|
Changed: Nested long comments and strings no longer allowed
|
||
|
Changed: x % 0 gives 0 (was x)
|
||
|
Optimised: software blitter now faster when using PocketCHIP, windowed raspi or blit_method 1
|
||
|
Fixed: infinite tokens exploit introduced in 0.2.5d (due to pre-processor changes)
|
||
|
Fixed: >>>= operator is a NOP (bug introduced in 0.2.5d)
|
||
|
Fixed: (raspi 32-bit) window not visible under Gameforce Chi / EmuELEC -- bug introduced in 0.2.5e
|
||
|
Fixed: fixed: s="x".."=" counts as 4 tokens instead of 5
|
||
|
Fixed: Running a cartridge containing _meta_ data prints a memory allocation warning to stdout
|
||
|
Fixed: Code compressing to >= 32k reports size as (compressed_size & 0x7fff) resulting in corruped exports
|
||
|
Fixed: stat(54) loops when left-most channel is looping (should return total played ticks on current pattern)
|
||
|
Fixed: extcmd("audio_rec") maximum length is 2 minutes (meant to be 8 -- and now only applies to web)
|
||
|
Fixed: Frog Home crashes because of (now unsupported) "local x+=.." form. // INSTALL_GAMES for fixed version
|
||
|
Fixed: Starting P8SCII font height affects total line height even when no characters are printed in that font
|
||
|
|
||
|
|
||
|
v0.2.5e
|
||
|
|
||
|
Fixed: Uppercase characters not loaded as punycode (causing _ENV to fail)
|
||
|
|
||
|
|
||
|
v0.2.5d
|
||
|
|
||
|
Added: tline(bits) to set number of bits used for fractional part of mx,my,mdx,mdy (13 by default)
|
||
|
Added: ctrl+mousewheel to scroll code horizontally
|
||
|
Added: current bbs cartridge id shown in window title (config.txt show_cart_id_in_title to disable)
|
||
|
Added: poke(0x5f36, (@0x5f36)|0x80) to enable character wrap by default when printing
|
||
|
Added: blit_method in config.txt // Can use a software blitter by default (slower but more reliable)
|
||
|
Added: reminder when re-locating sprites that only the top half of map is altered by default
|
||
|
Added: draw boot sound as note glyphs on startup when sound is off
|
||
|
Changed: print() returns both max(cur_x), max(cur_y) and includes non-printed characters (e.g. tabs)
|
||
|
Changed: extcmd("folder") and extcmd("set_title", "foo") can now be used from bbs carts
|
||
|
Changed: Indexing a string out of range returns nil (was "")
|
||
|
Changed: Replaced most of pre-processor with Lua parser modifications based on z8lua (fixes various edge cases)
|
||
|
Changed: "a[foo()] += 1" only evaluates foo() once
|
||
|
Changed: out-of-bound tile values can be drawn using map(), tline()
|
||
|
Changed: extcmd("audio_rec") can record a maximum of 8 minutes (was no limit previously)
|
||
|
Changed: Rate limits are now per-minute: 10MB of log wries, 64 different files, 10 extcmd("folder")'s)
|
||
|
Fixed: Infinite tokens hack (was caused by now-replaced pre-processor)
|
||
|
Fixed: Only 4 controllers mapped to 0x5f00+76
|
||
|
Fixed: h toggles hexadecimal mode in gfx editor (should be ctrl-h -- h is to flip sprite horizontally)
|
||
|
Fixed: out-of-bounds value doesn't respect custom map size
|
||
|
Fixed: cutting or clearing a selection of sprites does not also clear the sprite flags
|
||
|
Fixed: P8SCII repeat-character command fails on zero repetions; ?"a\*0bc" should print "ac", not "abc"
|
||
|
Fixed: pxa code compression inefficient when >= 32k matching triplets (typically "000")
|
||
|
Fixed: print() return value max(cur_x) returns 0 when max(cur_x < 0)
|
||
|
Fixed: holding menu button to force pause menu to open broken in binary exports
|
||
|
Fixed: copying / pasting in commandline doesn't respect punyfont character encoding
|
||
|
Fixed: (Manual) Steps 1 & 2 on how to move sprites in the map are in the wrong order
|
||
|
Fixed: Unhelpful / no error messages when the wrong format for HELP is used
|
||
|
|
||
|
|
||
|
v0.2.5c
|
||
|
|
||
|
Added: set out of range return value for sget, mget, pget: poke (0x5f36,0x10) and set at 0x5f59..0x5f5b
|
||
|
Changed: rnd(str) no longer returns a random char from strings (breaks existing carts using e.g. rnd"5")
|
||
|
Changed: html exports default to 75% volume instead of 100%
|
||
|
Fixed: extcmd("audio_rec"), extcmd("audio_end") not working in html exports
|
||
|
Fixed: drag & drop (via serial 0x802) not responding to dropped file in html exports
|
||
|
Fixed: (again) can enter an illegal note (e-5) in sfx editor
|
||
|
Fixed: dir() missing during runtime (alias for ls)
|
||
|
Fixed: some mistakes in help text (outdated sub() description, yield misspelling)
|
||
|
|
||
|
|
||
|
v0.2.5b (Linux)
|
||
|
|
||
|
Fixed: failing to drop down to wget when libcurl can not be loaded
|
||
|
|
||
|
v0.2.5
|
||
|
|
||
|
Added: Help topics. Use help command, or ctrl-u in code editor to get help on whatever is at the cursor.
|
||
|
Added: (html exports / bbs) downloadable .wav export using extcmd("audio_rec"), extcmd("audio_end")
|
||
|
Added: inext (to match next). -> can do: for i,v in inext,tbl do ... end
|
||
|
Added: floating selection layer in map editor (solves various bugs and undo / selection issues)
|
||
|
Added: ~ can be used as xor instead of ^^ (same as Lua 5.3/5.4)
|
||
|
Added: When running a program locally, ls() can now take a directory name; use stat(124) to get pwd
|
||
|
Added: Variable width P8SCII fonts
|
||
|
Added: ctrl-click on compressed capcity (bottom right) to get realtime updates of compressed size in bytes
|
||
|
Added: export -t @clip to get a hexdump of compressed code section copied to clipboard
|
||
|
Added: pico8 -scancodes and map_scancodes (config.txt) for manually mapping keys to alternative scancodes
|
||
|
Added: sub(str,pos,pos) can be written as str[pos]
|
||
|
Changed: host_framerate_control 1 (config.txt) now means "let PICO-8 decide"; is disabled for Mac/Win/Linux
|
||
|
Changed: in map editor, pan with cursor keys when nothing is selected
|
||
|
Changed: use scancodes for sfx navigation (US:-=_+) and spd change (US:,.<>) to avoid azerty collisions
|
||
|
Changed: gfx_grid_lines in config.txt is taken to be a colour for the grid lines (16 for black)
|
||
|
Changed: can ctrl-h in gfx editor to toggle hex mode (sprite index shown in hex; map vals shown)
|
||
|
Changed: '-' allowed in filenames when not first character
|
||
|
Changed: linux builds use libcurl.so for bbs requests, or drops down to wget on failure to dlopen
|
||
|
Changed: increased maximum gif len for web exports to 30 seconds
|
||
|
Changed: peek/poke can now read/write up to 32767 values (was 8192)
|
||
|
Changed: web player default gif len is 16 seconds (was 8)
|
||
|
Changed: sub(str, pos, nil) returns whole string (pre-0.2.4 behaviour). For single chars, can now use str[pos].
|
||
|
Fixed: Windows reserved filenames (lpt1, com1 etc) are accepted
|
||
|
Fixed: Nested coroutines unexpectedly end when interrupted by reaching end of frame
|
||
|
Fixed: print() colour is remapped twice when set in parameter // pal(6,7) pal(7,8) print("white",6)
|
||
|
Fixed: circ() breaks on 32-bit builds, with radius > 1024
|
||
|
Fixed: ctrl-c to copy commandline error message does not encode glyphs as unicode
|
||
|
Fixed: LS command not resolving relative paths
|
||
|
Fixed: twitter char count for chr(127) ○ should be 2 (was 1) and chr(149) ˇ should be 1 (was 2)
|
||
|
Fixed: colour parameter not converted from string in rect, rectfill, pset (regression from 0.2.2)
|
||
|
Fixed: ord("foo", 1, 0) returns "too many ord results" -- should return nothing
|
||
|
Fixed: save @url includes ?g= when no gfx data (is redundant)
|
||
|
Fixed: (web export) html pause button does not show up as btnp(6) / btn(6)
|
||
|
Fixed: (web export) codo_textarea triggering Mac accent character selector even when cart doesn't use clipboard
|
||
|
Fixed: save @url failing when encoded length is > 2000 chars long instead of > 2040 charss
|
||
|
Fixed: can enter an illegal note (e-5) in sfx editor
|
||
|
|
||
|
|
||
|
v0.2.4c
|
||
|
|
||
|
Added: save @url -- stores code + gfx as a URL if it can be encoded in 2040 characters
|
||
|
Added: html exports store volume/mute and other settings
|
||
|
Added: ctrl-g in sprite editor to toggle grid lines when zoomed in
|
||
|
Added: IMPORT -L FOO.PNG to import a 128x128 png to the cartridge label
|
||
|
Added: EXPORT -L FOO.PNG to export a 128x128 png of the cartridge label
|
||
|
Added: EXPORT -T FOO.P8.ROM to export only code section (t for tiny)
|
||
|
Added: ctrl-click on character count (bottom right) to see the twitter count (glyphs count as 2)
|
||
|
Added: __meta:*__ section to .p8 format -- can be used by external tools to store custom data
|
||
|
Added: extcmd("audio_rec") works from exported binaries, and with custom exported filenames
|
||
|
Added: read_controllers_in_background in config.txt (0 by default)
|
||
|
Added: periodic backups
|
||
|
Changed: .p8.rom files that are 0x3d00 bytes or less are loaded into code section
|
||
|
Changed: saved filenames can not include gylphs, or any of !"#$%&'()*+,-:;<=>?[\]^`{|}~
|
||
|
Fixed: can't drag and drop png into sprite editor
|
||
|
Fixed: binary exports: ctrl-r causes crash when there is no whitespace at end of source code
|
||
|
Fixed: Using -run switch to launch a cart that fails to run -> get stuck in boot screen.
|
||
|
Fixed: selection after ctrl-a reports length chars+1
|
||
|
Fixed: draw palette is not observed after changing colours using p8scii control characters
|
||
|
Fixed: music playback does not follow cursor after first pattern change (regression in 0.2.4b)
|
||
|
Fixed: transform_screen (config.txt) not observed by pause menus and other overlayed elements
|
||
|
Fixed: Double-clicking sfx thumbnail (in sfx overview screen) only works after playing music
|
||
|
Fixed: Pressing [a] to release looping sfx in sfx editor is broken
|
||
|
Fixed: sfx(46)..sfx(56) return -1 immediately after playing music but before host OS has called audio mixer
|
||
|
Fixed: Tokens counted as 2 instead of 1: ..= ^= >><= <<>=
|
||
|
Fixed: Negative number counted as 2 tokens instead of one when preceeded by: \ & | ^^ << >> >>> >>< <<>
|
||
|
Fixed: tostr(tbl) / print(tbl) acts like tostr(tbl, 1) when tbl has a metatable
|
||
|
Fixed: ?"\tx" does not advance to next tab stop
|
||
|
Fixed: ?"a\*5\nb" does not repeat newline 5 times
|
||
|
Fixed: exported label alpha is 0 for colour 0
|
||
|
|
||
|
|
||
|
|
||
|
v0.2.4b
|
||
|
|
||
|
Added: l in sprite sheet navigator to set loop start / end points (then q,w or a,z to navigate)
|
||
|
Added: ctrl-b in gfx editor to paste 2x2 original size ("paste big")
|
||
|
Added: DEL / backspace to clear selected region in gfx / map editors, and ctrl-x to cut
|
||
|
Added: aggressive_backups option in config.txt (off by default)
|
||
|
Added: transform_screen in config.txt to globally rotate / flip the video output
|
||
|
Added: stat(57) (boolean) true when music triggered by music() is playing or about to start
|
||
|
Changed: memset() faster than using peek4/poke4; now 2 cycles per byte at 8MHz (was 4)
|
||
|
Changed: "running at < 30fps" warning on boot now only for raspi builds, and w/ higher tolerance
|
||
|
Changed: Controller inputs are accepted even when PICO-8 is not the foreground application
|
||
|
Changed: Map can be located at 0x1000 .. 0x2f00 using poke(0x5f56, 0x11) .. poke(0x5f56,0x2f)
|
||
|
Changed: Dotty text mode is now "\^=" ("Stripey") instead of "\^." // #gunayawuho #klax #impossible
|
||
|
Fixed: (not confirmed) crash causing 0-byte .p8 when audio mixer is called during save / run
|
||
|
Fixed: preprocessor not counting comments as white space; should allow: ".. end--[[]]if .."
|
||
|
Fixed: pal(nil) behaving the same way as pal(0); should be same as pal() // broke #rtype-2
|
||
|
Fixed: note entry in sfx tracker is silent after running cartridge until pressing space to playback
|
||
|
Fixed: sub("abc", 4, 4) returns "c" (regression in 0.2.4)
|
||
|
Fixed: SPLORE cart update prompt does not appear when server replies too quickly (race condition)
|
||
|
Fixed: SPLORE cart update prompt only checks version once per session (can't refresh until it shows up)
|
||
|
Fixed: EXPORT command does not flatten includes when exporting to .p8.png / .p8.rom format
|
||
|
Fixed: EXPORT command discards source code changes since last run or load
|
||
|
Fixed: printing a one-off glyph using "\^." terminates the whole string when last byte is a zero
|
||
|
Fixed: Crash when loading a cart with fewer tabs, then creating a new tab and pasting.
|
||
|
Fixed: . command runs at 30fps even for a 60fps cart (-> _update60 is called twice, _draw once)
|
||
|
Fixed: Custom menu items become broken after suspending a cart, entering a lua command, and then resuming
|
||
|
Fixed: memset() with a non-zero value in shared memory region (0x1000..0x1fff) causes garbage corresponding mget() values
|
||
|
Fixed: web player/exports: ctrl-r causes erroneous "external changes reloaded" message and code corruption
|
||
|
|
||
|
|
||
|
v0.2.4
|
||
|
|
||
|
Added: Video and spritesheet memory addresses can be mapped to each other
|
||
|
Added: Map memory address can be mapped to 0x8000 // POKE(0x5f56, 0x80)
|
||
|
Added: stat(46)..stat(56): higher resolution and more accurate reporting of audio state
|
||
|
Added: Print one-off characters with ?"\^:447cb67c3e7f0106 hey" (or "\^." for binary data)
|
||
|
Added: chr() can take multiple arguments to construct an arbitrarily long string
|
||
|
Added: sub(str, pos, _) to get a single character at position pos
|
||
|
Added: Warning on boot when PICO-8 is running below 30fps
|
||
|
Added: Automatic scrolling caused by print() (with no x,y given) can be disabled with POKE(0x5f36,0x40)
|
||
|
Added: .p8.rom format can be used by cstore(), reload() and in multicarts
|
||
|
Added: EXPORT accepts .p8 .p8.png .p8.rom formats (can be used to save a copy, or convert from commandline)
|
||
|
Added: 64-bit RaspberryPi OS Builds and Exporters
|
||
|
Added: ASCII .txt version of manual included in archives & on website (synced with new html version)
|
||
|
Added: Auto-hide mouse cursor when typing (adjustable in config.txt)
|
||
|
Changed: .p8.rom file format can be less than 32k -- is padded with zeros to 32k on load
|
||
|
Changed: sub() costs some cpu based on the length of the string
|
||
|
Changed: Shorthand if/while no longer needs to be preceeded by a whitespace character or number
|
||
|
Changed: load("#") throws a runtime error when cartridge id contains illegal characters
|
||
|
Changed: 64k of Base RAM is standard (no need to set the hardware extension bit)
|
||
|
Changed: By default, draw colour resets to 6 when program is suspended
|
||
|
Changed: map() can take nil parameters for source_w, source_h to indicate default values
|
||
|
Changed: pal(n) (a single integer) to reset a single palette 1..3 (draw, display, secondary)
|
||
|
Changed: Can turn P8SCII wrap on/off with "\^$", "\^-$"
|
||
|
Changed: config.txt is not saved on exit when changes are made to it while PICO-8 is open
|
||
|
Changed: added code editor undo points when changing between identifier and non-identifier characters
|
||
|
Changed: sfx(-1, -2) now behaves the same as sfx(-1). sfx(-2) stops looping on all channels.
|
||
|
Changed: chip build no longer requires libcurl (calls out to wget)
|
||
|
Fixed: (Mac, Linux) load("#`echo ohno`") is executed // + server-side mitigation for splore
|
||
|
Fixed: stat(31) returns 2 parameters (bug introduced in 0.2.3)
|
||
|
Fixed: split() and sub() fail on strings containing "\0"
|
||
|
Fixed: ctrl-x on song pattern appears to work, but music() plays sfx 1..4
|
||
|
Fixed: Text getting cut off after console scrolling when using print with draw_y_offset (0x5f5b)
|
||
|
Fixed: camera(0,128) cursor(0,128) print("\n") causes unnecessary console scrolling
|
||
|
Fixed: last music pattern not saved when only channel 3 is used and other channels are defaults
|
||
|
Fixed: ?"\a12 sup yall" overwrites sfx 12 with a default beep (should just play and continue printing)
|
||
|
Fixed: cursed console cpu refund exploit // https://carlc27843.itch.io/cursed-console
|
||
|
Fixed: ctrl-r from commandline resets parameter string (stat(6)) -- should be same as the last run
|
||
|
Fixed: ord() corrupting Lua stack and crashing when returning more than ~80 results
|
||
|
Fixed: large camera() parameters can cause line() clipping to fail and crash
|
||
|
Fixed: Crash when saving long gifs (> 90 seconds)
|
||
|
Fixed: Unmapped joysticks not responding
|
||
|
Fixed: Plugging in > 2 controllers causes other controller to disconnect
|
||
|
|
||
|
|
||
|
v0.2.3
|
||
|
|
||
|
Added: Lucky draw list in splore -- gives a random selection of carts
|
||
|
Added: load/save carts in .p8.rom format (raw binary 32k block)
|
||
|
Added: tostr(), tonum() take format_flags parameter to convert to and from 32-bit signed ints
|
||
|
Added: ord(str, pos, num) returns num results starting from character at pos (similar to peek)
|
||
|
Added: FOLDER takes an optional parameter to open other host directories: BACKUPS | DESKTOP | CONFIG | BBS
|
||
|
Added: Live character / token count of selected text shown at bottom right of code editor
|
||
|
Changed: Removed collaboration list from splore (can still search for sub:collab)
|
||
|
Changed: 0x808 audio has a slight lpf filter on it by default // turn off by setting bit 0x20 at 0x5f36
|
||
|
Changed: tonum(boolean_value) returns 1 or 0 instead of nil
|
||
|
Changed: cursor CR x position set only by print(str,x,y) or cursor(), but not by print(str) (0x5f24)
|
||
|
Changed: character wrap is on by default when using print(str)
|
||
|
Changed: force-pause-menu hold duration is 500ms instead of 300ms to prevent accidentally triggering it
|
||
|
Changed: default gif length for new install is 16 seconds
|
||
|
Changed: ? shorthand can be used anywhere on a line e.g. if (true) ?"yes"
|
||
|
Changed: allow while/if shorthand with no statement, using colon separator: WHILE(BTN()==0);
|
||
|
Changed: added warning to fullscreen_method 2 in config.txt (gives erratic behaviour under some drivers)
|
||
|
Changed: cheaper OP_MOVE, OP_UNM lua vm instructions so that e.g. "local a=0-b" is not faster than "local a=-b"
|
||
|
Fixed: peek*() / poke*() do not charge extra cpu when reading or writing multiple values
|
||
|
Fixed: fget(n) returns junk when n is out of range (0..255); should return 0 in that case
|
||
|
Fixed: dropped .PNG files not detected as images when filename uses uppercase extension
|
||
|
Fixed: line()/tline() illegal writes caused by faulty clipping when (x1-x0) or (y1-y0) >= 0x8000
|
||
|
Fixed: -accept_future 1 only worked with .p8.png files; now also applies to .p8
|
||
|
Fixed: ?"\a7f" does not play f (happens only when f is the first note)
|
||
|
Fixed: abs(0x8000) return 0x0.0001 (should be 0x7fff.ffff)
|
||
|
Fixed: parameter string (stat(6)) is dropped when passed via RUN command
|
||
|
Fixed: preprocessing of form: "x += x<0 and -1 or 1" broken for operators <, >
|
||
|
Fixed: tab not accepted as whitespace for some preprocessor operations
|
||
|
Fixed: stat(1) wraps around when cpu is >= 2.0 (regression in 0.2.2)
|
||
|
Fixed: pressing SHIFT+ENTER on "local function foo()" or after "if (..) else" doesn't insert "end"
|
||
|
Fixed: pal() does not reset secondary palette to system default
|
||
|
Fixed: 0x808 audio does not respect pausing / volume / is not recorded with extcmd("audio_rec")
|
||
|
Fixed: 'h' pressed in sprite editor toggles hex mode in map editor
|
||
|
Fixed: After pressing shift-tab to toggle 128x128 map view, active draw area is still only 128x112
|
||
|
Fixed: Attempt to navigate to non-existant tab after running: function _update60() _update60=nil end
|
||
|
Fixed: stat(101) not returning cart id when running from BBS web player
|
||
|
Fixed: print() wrapping + scrolling; e.g. from commandline: while(true) print(chr(254+rnd(2)).."\0")
|
||
|
Fixed: integer divide assignment operator (\=) costs 2 tokens instead of 1
|
||
|
|
||
|
|
||
|
v0.2.2c
|
||
|
|
||
|
Fixed: ?"\ac0" starts from d#0 instead of c0 (again -- 0.2.2b was still broken)
|
||
|
Fixed: splore local directory navigation fails when using a relative home path set with -home
|
||
|
Fixed: export .lua.png only shows the first 2730 lines
|
||
|
|
||
|
|
||
|
v0.2.2b
|
||
|
|
||
|
Added: export foo.lua.png to get an image of the cartridge's source code
|
||
|
Added: Pause menu can be forced to appear by holding down pause for 300ms (even if program blocks it)
|
||
|
Added: extcmd("set_filename","foo") -- set the filename of the next screenshot or gif (can include %d)
|
||
|
Added: extcmd("set_title","foo") -- set window title (useful for exported binaries)
|
||
|
Added: Can toggle punyfont mode at command prompt w/ ctrl+p (useful for inspecting puny variable names!)
|
||
|
Changed: Default filename is /untitled.p8 instead of no filename (auto-increments to untitled_1.p8 etc.)
|
||
|
Changed: circ/oval that are not visible cost almost nothing, including circles that contain clipping region
|
||
|
Changed: filled circles/ovals that contain clipping region cost the same as the equivalent rectfill
|
||
|
Changed: shift+enter in code editor only auto-completes block for DO, THEN, REPEAT or FUNCTION
|
||
|
Fixed: ?"\ac0" starts from d#0 instead of c0
|
||
|
Fixed: preprocessor regression when using string at end of ..= statement: if (true) then a..="b" end
|
||
|
Fixed: pressing L / R in paused menu is registered by running program after closing menu
|
||
|
Fixed: printing text in tall mode (?"\^ttall") via commandline can chop off bottom line before scrolling
|
||
|
Fixed: drag-select text with cursor at bottom or top of screen scrolls too fast
|
||
|
Fixed: spurious stat(0) results when using yield() to exit frame instead of flip()
|
||
|
Fixed: line()/tline() sometimes draws pixels on opposite side of screen (0.2.2 regression)
|
||
|
Fixed: line()/tline() fails to draw lines that have x or y coordinates > 32767 pixels apart
|
||
|
Fixed: can peek() more than 8192 values in single call
|
||
|
Fixed: large fill circles (> radius 900) render incorrectly close to vertical center (32-bit builds, web)
|
||
|
Fixed: even-widthed filled ovals with midpoint < 0 is drawn off by 1
|
||
|
Fixed: black pixels in gif / map export not completely black
|
||
|
Fixed: map and spritesheet exporters do not respect current display palette and 0x5F36:0x8 (draw spr 0)
|
||
|
Fixed: code editor: cursor position off by one when selecting character after glyph (0.2.2 regression)
|
||
|
Fixed: code editor: tab names don't show up when 100% punyfont
|
||
|
Fixed: import spritesheet.png failing under MacOS (0.2.2 regression)
|
||
|
Fixed: export single sfx to .wav crashes when contains sfx instrument references
|
||
|
|
||
|
|
||
|
v0.2.2
|
||
|
|
||
|
Added: SFX filters: noiz (white noise for inst 6), buzz, detune (flange/overtone), reverb, dampen (lpf)
|
||
|
Added: SFX length (leave the second loop value at 0 to use). Can be >= 32.
|
||
|
Added: P8SCII control characters when using print() -- can adjust colour and cursor position etc.
|
||
|
Added: User-defined font at 0x5600, accessible via control character \014
|
||
|
Added: poke(addr, val0, val1, val2 .. valn) -- same for poke2, poke4
|
||
|
Added: can peek multiple values: a,b,c = peek(addr, 3) -- same for peek2, peek4
|
||
|
Added: Locked mouse pointer // poke(0x5f2d, 0x5) and then stat(38),stat(39) to read
|
||
|
Added: right click in sfx pitch mode to grab the instrument of that note
|
||
|
Added: IMPORT command can specify target location in pixels: IMPORT FOO.PNG -X 16 -Y 32
|
||
|
Added: IMPORT -S to shrink the imported image (e.g. -S 3 means shrink from 384x384 -> 128x128)
|
||
|
Added: ctrl-c at empty command prompt to copy the most recent error message
|
||
|
Added: extcmd("screen",0,1) / extcmd("video",0,1) saves files in same path as cart / exported executable or app.
|
||
|
Added: set bit POKE(0x5F36, 0x8) to treat sprite 0 as opaque when drawn by map(), tline()
|
||
|
Added: shift-tab in gfx/map editor for full-fullscreen mode (with no red menu bars)
|
||
|
Added: extcmd("rec_frames") to record each gif frame only when flip() is called regardless of rendering speed
|
||
|
Added: extcmd("folder") to open the folder on the host operating system (where printf, extcmd saves files to)
|
||
|
Added: custom menu callbacks can optionally leave the pause menu open, and can read LEFT and RIGHT button presses
|
||
|
Added: ctrl-h hex mode in map / gfx views (displays current sprite in hex, and shows map tile values)
|
||
|
Added: export map as a single image with export foo.map.png
|
||
|
Added: @weeble's gamepad improvements to the default html shell (dpad layout detection, better mapping / hotplugging)
|
||
|
Added: stack trace on bad memory access e.g. poke(-1,0)
|
||
|
Added: fillp can now be applied to sprite drawing (spr / sspr / map / tline), using colours from the secondary palette
|
||
|
Improved: General optimisation pass; heavy carts use 20~30% less host cpu
|
||
|
Changed: Most api functions are local by default for performance. use "pico8 -global_api 1" if needed for debugging.
|
||
|
Changed: unpack() now has a non-zero cost but still fairly fast
|
||
|
Changed: .. operator has a small cost based on number of characters concatenated
|
||
|
Changed: LOADK vm instruction costs 1 cycles (was 2) // otherwise "c=0" costs more than "c=a+b"!
|
||
|
Changed: removed function cpu refunds; speed-critical calls to bitwise function should use operator counterparts instead.
|
||
|
Changed: Incremental garbage collection each frame for improved performance.
|
||
|
Changed: stat(0) performs garbage collection in order to obtain a meaningful result; use stat(99) for raw value
|
||
|
Changed: options menu always available from pause menu (used to only be available in web exports)
|
||
|
Changed: tostr() returns "" instead of nil
|
||
|
Changed: exporting gif/png from web version now creates a pop-up div that can be dismissed
|
||
|
Changed: print() from commandline automatically wraps long strings
|
||
|
Changed: print() returns the x position of the next character to be printed (can be used to calculate text width)
|
||
|
Changed: glyph constants set only when running cartridge, not when running a command from prompt
|
||
|
Changed: Using printh from exported carts outputs files in the same folder as the .exe / .app
|
||
|
Changed: type() returns nothing instead of causing a runtime error
|
||
|
Changed: fill pattern is cleared when program is suspended by default. Use poke(0x5f2e,0x20) to preserve.
|
||
|
Changed: reset() resets everything from 0x5f00..0x5f7f, same as when program is initialised (including new random seed)
|
||
|
Changed: font tweaks for hiragana, katagana, ampersand characters
|
||
|
Changed: (raspi) separate binaries that support gpio to remove wiringPi dependency and gpio poking-related crashes
|
||
|
Fixed: Diagonal lines in editor contain an incorrect step when snapping to -1:1, 1:-1
|
||
|
Fixed: rnd(tbl) is not random enough when table has 2 elements /bbs/?pid=81092#p
|
||
|
Fixed: add(tbl) causes runtime error. should have no effect and return nothing
|
||
|
Fixed: cursor position in code editor incorrect when changing lines contaning glyphs/tabs
|
||
|
Fixed: CONFIG TAB_WIDTH does not take effect until restarting PICO-8
|
||
|
Fixed: Selecting sprites from bottom right -> top left and then pasting only pastes a single sprite
|
||
|
Fixed: Moving map selection around with cursor keys beyond original selection leaves streaks
|
||
|
Fixed: stdout/stdin serial() streams should be binary, not text mode (causes \r chars under Windows)
|
||
|
Fixed: printh("hello.txt",fn,true,true) fails to save to desktop when fn has an extention
|
||
|
Fixed: IMPORT FOO.PNG using the current sprite location as target instead of 0,0
|
||
|
Fixed: tonum behaving differently to parser for string numbers out of range. e.g. tonum("-0x9000") should be 0x7000
|
||
|
Fixed: Exporting the same zip file multiple times creates duplicate file entries
|
||
|
Fixed: tline / line clipping // sometimes off by 1px, sometimes incorrectly discarded altogether
|
||
|
Fixed: poking values with bit 0x80 to 0x5f28,0x5f30,0x5f3c,0x5f3e clobbers following address
|
||
|
Fixed: deli(tbl,nil) behaves the same as deli(tbl) -- should have no effect
|
||
|
Fixed: stat(13),stat(15) reporting y coordinates of menu with 0 items
|
||
|
Fixed: memory leak when saving gifs (causes web export to crash after a few records)
|
||
|
Fixed: print() linefeeds clobber multi-line text printed at bottom of screen
|
||
|
Fixed: preprocessor can not handle form: "::_::a+=1" (regression in 0.2.1)
|
||
|
Fixed: When split() by group size (e.g. split("ab12",2,false)), last parameter ignored
|
||
|
Fixed: partial cstore (len < 0x4300) from splore/export clobbering data outside that range on subsequent reload
|
||
|
Fixed: joystick stops responding after unplug and plug back in twice (also happens when some devices sleep / wake up)
|
||
|
Fixed: mkdir(nil) crashes
|
||
|
Fixed: possible to edit an SFX without the cursor visible (confusing)
|
||
|
Fixed: menuitem() callbacks broken when there is no _draw() or _update() defined
|
||
|
Fixed: should only be able to call from commandline: cd mkdir install_games keyconfig info
|
||
|
Fixed: controller menu (pause->options->controls) does not show custom key settings
|
||
|
Fixed: -export failing to find files relative from current path
|
||
|
Fixed: -export failing to locate html template path
|
||
|
Fixed: binary export storing multicart cart names with path (should be named "dat1.p8", not "dat/dat1.p8")
|
||
|
Fixed: pause menu broken when cartridge is launched from splore and run() is called inside first frame
|
||
|
Fixed: text printing does not respect draw palette (was broken in 0.2) // ref: /bbs/?tid=41428
|
||
|
Fixed: for backwards compatibility, non-numbery colour parameters should be taken to mean zero
|
||
|
Fixed: preprocessor: self assignment with quoted function calls on RHS a+=1+cos"0"
|
||
|
Fixed: ctrl-r during pause menu only takes effect after closing menu
|
||
|
Fixed: (bug in RC1) pack(...).n is zero
|
||
|
Fixed: (bug in RC1) using filters noiz:1, dampen:2, lpf is not applied to melodic instruments (but should be)
|
||
|
|
||
|
|
||
|
v0.2.1b
|
||
|
|
||
|
Added: split(str,"") splits by single characters
|
||
|
Updated: Tower of Archeos 1.1 via INSTALL GAMES
|
||
|
Fixed: print(num,x,y) always prints numbers num in hexidecimal
|
||
|
Fixed: .p8.png decoder can enter an infinite loop (caused exports to freeze on boot)
|
||
|
Fixed: Can't save screenshot/gif when running a BBS cart with illegal characters in title.
|
||
|
Fixed: INSTALL_GAMES is broken
|
||
|
Fixed: Mouse is broken in HTML exports
|
||
|
|
||
|
|
||
|
v0.2.1
|
||
|
|
||
|
Added: oval() ovalfill() split()
|
||
|
Added: circle drawing tool is now an oval tool (hold shift for circle)
|
||
|
Added: hold shift with line tool to snap to 22.5 degree angles from origin (0:1, 1:1, 2:1 gradients)
|
||
|
Added: serial() channels for stdin,stdout
|
||
|
Added: raw binary and image files dropped in to PICO-8 also become byte streams readable w/ serial()
|
||
|
Added: add(tbl, val, index) -- insert val into table at index
|
||
|
Added: deli(tbl, index) -- delete element from table by index (index defaults to last element)
|
||
|
Added: show progress while exporting binaries (can be slow now that generating zip files)
|
||
|
Added: -e to add an extra file to exported binaries zip files // export -e manual.txt foo.bin
|
||
|
Added: RESET command to reset the runtime / draw state
|
||
|
Added: drag and drop cartridges into PICO-8 window to load them
|
||
|
Added: hash stored in .p8.png so that cartridges corrupted by image quantization can show a specific error
|
||
|
Added: raw data blocks in compressed code format (useful for storing long binary strings efficiently)
|
||
|
Added: clip(x,y,w,h,true): 5th parameter indicates that the clipping region should be clipped by the old one
|
||
|
Added: -export switch can be used to convert .p8 files to .p8.png from commandline. // pico8 foo.p8 -export foo.p8.png
|
||
|
Added: extcmd("screen",scale) and extcmd("video",scale) to override the default scale (e.g. scale 2 means 256x256)
|
||
|
Added: printh(str, filename, overwrite, save_to_desktop) -- 4th parameter to save output file to desktop
|
||
|
Changed: add(), del() no longer implemented with Lua snippet; lower cpu cost.
|
||
|
Changed: line(),rect() cost the same as rectfill() when drawing equivalent shapes
|
||
|
Changed: all drawing operations in sprite editor now observe fill pattern state
|
||
|
Changed: numbers can be immediately followed by identifiers (a=1b=2) // lexaloffle.com/bbs/?tid=38038
|
||
|
Changed: Sprite editor shows only active area after shift-selecting sprites
|
||
|
Changed: copy/paste in the code editor treats uppercase ascii characters as puny font only when puny mode (ctrl+p) enabled
|
||
|
Changed: C0 Controls characters (except for 0x0,0x9,0xa,0xd) encoded in .p8 / clipboard with unicode replacements
|
||
|
Changed: stat(4) converts characters to PICO-8 format (P -> puny p, hiragana unicode -> single character etc.)
|
||
|
Changed: serial() returns number of bytes processed (1/8ths included for partial bytes)
|
||
|
Changed: IMPORT SPRITESHEET.PNG now uses the current sprite as the destination coordinate instead of 0,0.
|
||
|
Changed: Standardized name of the display palette to "display palette" (was sometimes referred to as "screen palette").
|
||
|
Changed: tostr() returns nil (used to return "[nil]")
|
||
|
Changed: don't need to set bit 0x40 at address 0x5f2c to use secondary palette.
|
||
|
Improved: exported binary's data.pod file 90% smaller (~870k -> ~85k)
|
||
|
Fixed: pack(...).n is shifted right 16 bits
|
||
|
Fixed: ctrl-r doesn't reload external changes for carts which are over compressed code capacity
|
||
|
Fixed: false positives when detecting external changes for some older cart versions
|
||
|
Fixed: .p8.png carts saved with dense code (compressed size > raw size, including very small carts) stores junk
|
||
|
Fixed: error message duplication when loading future version of .p8.png carts
|
||
|
Fixed: Illegal colours can enter spritesheet via serach-replace after setting with color()
|
||
|
Fixed: Preprocessor: "foo():a().x+=1" "a=b[1]c+=1"
|
||
|
Fixed: hex numbers written with punyfont characters breaks syntax high-lighting
|
||
|
Fixed: shift+- in sprite editor jumps too far vertically when zoomed in
|
||
|
Fixed: clicking a note in sfx editor creates a selection (-> backspace clears without moving rows)
|
||
|
Fixed: print()/printh()/stop() doesn't respect __tostring metatable method (regression)
|
||
|
Fixed: time() and btnp() speed changes after stopping program, typing a command and then resuming.
|
||
|
Fixed: phantom drag & drop events sent to unused music channels causing them to occasionally unmute themselves
|
||
|
Fixed: undo after moving sprites in map mode only undoes the changes to the map and not the spritesheet.
|
||
|
Fixed: inconsistent token counting for negative or bnot'ed numbers https://www.lexaloffle.com/bbs/?tid=38344
|
||
|
Fixed: Crash when INSTALL_GAMES / INSTALL_DEMOS without a writeable disk
|
||
|
Fixed: stat(4) (clipboard contents) does not convert unicode to corresponding glyphs
|
||
|
Fixed: (MacOS) Using discrete GPU ~ drains battery. Now using integrated GPU when available.
|
||
|
Fixed: screensaver is blocked while PICO-8 is running (needed to set SDL_HINT_VIDEO_ALLOW_SCREENSAVER: "1")
|
||
|
Fixed: screen glitches after running for 25 days
|
||
|
Fixed: (HTML Exports) touch controls not registering when running under iOS from an iframe (e.g. on an itch.io page)
|
||
|
Fixed: (HTML Exports) tap and hold brings up the select menu under iOS
|
||
|
Fixed: (HTML Exports) button blocked by canvas when overlapping on small screens
|
||
|
|
||
|
|
||
|
|
||
|
v0.2.0i
|
||
|
|
||
|
Added: pack(), unpack()
|
||
|
Changed: bitplane read/write mask only reset after finished running program
|
||
|
Fixed: tline() doesn't draw anything when the layers argument is not given
|
||
|
|
||
|
|
||
|
v0.2.0h
|
||
|
|
||
|
Added: tline() takes an optional layers parameter, similar to map()
|
||
|
Added: high bits of 0x5f5e taken as colour read mask, low taken to be colour write mask
|
||
|
Added: Double-click in the sfx tracker to select all attributes of a single note.
|
||
|
Fixed: assignment shorthand RHS scope wrong when contains certain operators. e.g. a+=1&127
|
||
|
Fixed: while/if shorthands fail when "do" or "then" appears on the same line as part of an identifier
|
||
|
Fixed: ctrl-c copies the wrong sfx after clicking pencil button (next to pattern #) in organiser view
|
||
|
Fixed: spinning cart icon present in video memory when cart boots from splore
|
||
|
|
||
|
|
||
|
v0.2.0g
|
||
|
|
||
|
Added: Window title shows current cartridge filename while editing
|
||
|
Changed: ~ preceeding a numerical constant (e.g. ~1) counts as a single token
|
||
|
Fixed: >>> operator behaviour does not match lshr(a,b) when b >= 32 (again)
|
||
|
Fixed: PICO-8 freezes when shift by -0x8000
|
||
|
Fixed: .p8 format does not store extpal label colours
|
||
|
Fixed: Can not save screenshot when filename contains ":"
|
||
|
|
||
|
|
||
|
v0.2.0f
|
||
|
|
||
|
Changed: @@ operator (peek2) to %
|
||
|
Fixed: Exported wasm crashes on boot when code contains a numerical constant out of range.
|
||
|
Fixed: HTML Shell treats controller shoulder buttons as MENU; easy to accidentally bump.
|
||
|
Fixed: shift operators behaviour undefined for negative values of n (now: x << n means x >> -(n\1))
|
||
|
Fixed: >>> operator behaviour does not match lshr(a,b) when b >= 32
|
||
|
Fixed: INFO crashes when code is close to 64k of random characters
|
||
|
Fixed: Code editor undo step not stored when starting to edit a new line (hard to see what happened)
|
||
|
|
||
|
|
||
|
v0.2.0e
|
||
|
|
||
|
Added: zip file creation (with preserved file attributes) when exporting binaries
|
||
|
Added: cpu working animation when cpu usage > 120 skipped frames
|
||
|
Improved: stop() / resume now works at the instruction level
|
||
|
Fixed: tline clipping broken (from 0.2.0d)
|
||
|
Fixed: cpu counting is wrong inside coroutines
|
||
|
Fixed: coroutines interrupted by garbage collection
|
||
|
Fixed: code compression suddenly much worse for carts > 32k chars
|
||
|
Fixed: code compression ratio can be less than 1 in extreme cases
|
||
|
Fixed: pasting a string ending in '1' into the command prompt opens the editor
|
||
|
Fixed: html export can run out of pre-allocated heap when doing heavy string operations
|
||
|
Fixed: hex memory addresses displayed in puny font on windows
|
||
|
Fixed: devkit mouse message shown once per cart -- should be once per chain of carts
|
||
|
Fixed: can't paste sfx notes after moving to another sfx via keyboard
|
||
|
Fixed: copying note select vs. sfx vs. pattern range is ambiguous
|
||
|
Fixed: crash after redefining type()
|
||
|
|
||
|
|
||
|
v0.2.0d
|
||
|
|
||
|
Added: rnd(x) when x is an array-style table, returns a random item from that table
|
||
|
Added: gif_reset_mode (in config.txt / CONFIG command). Defaults to 0.1.12c behaviour
|
||
|
Added: print(str, col) form behaves the same as: color(col) print(str)
|
||
|
Added: Operators: <<> >>< <<>= >><=
|
||
|
Changed: tline now also observes an offset (0x5f3a, 0x5f3b)
|
||
|
Changed: tline rounds down to integer screen coordinates (same as line)
|
||
|
Changed: Final cpu adjustments (see release post)
|
||
|
Changed: Removed experimental "!"->"this" shorthand
|
||
|
Changed: clip() returns previous state as 4 return values
|
||
|
Fixed: Included files remain locked (and can not be edited by external editors)
|
||
|
Fixed: Carts loaded as plaintext .lua fail to handle BOM / DOS characters
|
||
|
Fixed: palt() returns previous state of bitfield as a boolean instead of a number
|
||
|
Fixed: CPU speed on widget doesn't exactly match stat(1)
|
||
|
Fixed: stat(1) occasionally reports garbage values when above 1.0
|
||
|
Fixed: Custom btnp repeat rates (0x5f5c, 0x5f5d) speed up when skipping frames
|
||
|
Fixed: gif_scale setting not read from config.txt
|
||
|
Fixed: tline: texture references are incorrect when sy1 < sy0
|
||
|
Fixed: tline: single pixel spans are drawn as two pixels
|
||
|
Fixed: binary exports' controls menu always shows 0 joyticks connected
|
||
|
Fixed: Pressing DEL on first row of tracker doesn't do anything
|
||
|
Fixed: host framerate regulation is slow (~1/sec) when PICO-8 frame takes < 1ms to execute
|
||
|
Fixed: fillp() return value (previous state) does not include transparency bit
|
||
|
Fixed: clip"" setting all clip values to 0 (should be ignored)
|
||
|
Fixed: Raspberry Pi static build / static export requires GLIBC 2.0.29 (now .16)
|
||
|
Fixed: stop(nil) crashes
|
||
|
Fixed: print(), printh(), stop() prints "nil" with no arguments (should have no output)
|
||
|
Fixed: trace() can not be used with coroutines
|
||
|
|
||
|
|
||
|
v0.2.0c
|
||
|
|
||
|
Changed: Compressed size limit now 0x3d00 bytes (reclaimed an unused 0x100 byte block)
|
||
|
Fixed: >>>= operator (was doing a >>= replacement instead)
|
||
|
Fixed: #including large .lua files causes crashes, weird behaviour
|
||
|
Fixed: Sandboxed CSTORE: writing partial data to another embedded cart clobbers the remaining data.
|
||
|
Fixed: Multicart code storing regression introduced in 0.2.0 (code from head cart stored in other carts)
|
||
|
Fixed: Can not edit spritesheet after panning
|
||
|
Fixed: Junk error messages when syntax error contains one of the new operators
|
||
|
Fixed: Crash with: 0x8000 / 1
|
||
|
|
||
|
|
||
|
v0.2.0b
|
||
|
|
||
|
Changed: #include directive can be preceeded by whitespace
|
||
|
Changed: Activity logger records nothing after idle for 30 seconds
|
||
|
Fixed: Mouse cursor movement in editor is not smooth
|
||
|
Fixed: Display palette doesn't reset after exiting splore
|
||
|
Fixed: PALT() returns 0 instead of previous state as bitfield
|
||
|
Fixed: Rectangle and line tools broken when used in map editor
|
||
|
Fixed: INSTALL_GAMES under Windows produces broken cart files
|
||
|
Fixed: Stored multicart sometimes has code section truncated (fails to load())
|
||
|
|
||
|
|
||
|
v0.2.0
|
||
|
|
||
|
Added: 8-bit character set with kana, alt font
|
||
|
Added: ord(), chr()
|
||
|
Added: SFX / Pattern organiser view
|
||
|
Added: SFX edit buttons on pattern channels
|
||
|
Added: tline // textured line drawing
|
||
|
Added: SPLORE automatically updates BBS carts when online
|
||
|
Added: Search for similar (shared tags) cartridges, or by thread
|
||
|
Added: predefined fillp() pattern values assigned to glyphs
|
||
|
Added: btnp() custom delays (poke 0x5f5c, 0x5f5d)
|
||
|
Added: "." shorthand command for advancing a single frame (calls _update, _draw if they exist)
|
||
|
Added: Current editor/cart view is recorded every 3 seconds to [app_data]/activity_log.txt
|
||
|
Added: Cutting (ctrl-x) and pasting selected sprites while in map view to also adjust map references to those sprites
|
||
|
Added: Clipboard is supported in the html exports (with some limitations) // load #wobblepaint for an example.
|
||
|
Added: Can load .lua files as cartridges
|
||
|
Added: Operators: ..= ^= \ \= & | ^^ << >> >>> ~ &= |= ^^= <<= >>= >>>= @ @@(update: @@ replaced with %) $
|
||
|
Added: New demo carts: waves.p8 dots3d.p8 automata.p8 wander.p8 cast.p8 jelpi.p8 (use INSTALL_DEMOS)
|
||
|
Added: Extra pre-installed games: Embrace, 8 Legs to Love (use INSTALL_GAMES)
|
||
|
Added: Splore cart labels for .p8 files
|
||
|
Added: Now 16 code tabs (click on the rightmost ones to scroll)
|
||
|
Added: ipairs()
|
||
|
Added: SAVE from commandline to quick-save current cartridge (same as ctrl-s)
|
||
|
Added: BACKUP from commandline to save a backup of current cartridge
|
||
|
Added: CPU usage widget (ctrl-p while running cartridge)
|
||
|
Added: Button / dpad states exposed in memory at 0x5f4c (8 bytes)
|
||
|
Added: Random number generator state exposed at 0x5f44 (8 bytes)
|
||
|
Added: pico8_dyn version is included when exporting to Raspberry Pi
|
||
|
Added: allow_function_keys option in config.txt (CTRL 6..9 are now preferred -- will phase out F6..F9 if practical)
|
||
|
Added: Visible tab characters (draw_tabs in config.txt)
|
||
|
Added: pal({1,2,3..}) means: use the value for each key 0..15 in a table
|
||
|
Added: palt(bitfield) means: set the colour transparency for all 16 colours, starting with the highest bit
|
||
|
Added: Options menu for binary exports (sound / fullscreen / controls)
|
||
|
Added: Shape drawing tools in sprite and map editor
|
||
|
Improved: Miscellaneous HTML shell / player optimisations and adjustments
|
||
|
Improved: Lower cpu usage for small foreground_sleep_ms values (changed host event loop & fps switching strategy)
|
||
|
Changed: This update is called 0.2.0, not 0.1.12d! (grew into plans for 0.2.0, and bumped cart version number)
|
||
|
ChangeD: Reverted cheaper 0.1.12* costs on bitwise operators & peek (recommend replacing with operators if need)
|
||
|
Changed: negative numbers expressed with a '-' count as a single token
|
||
|
Changed: glitchy reset effect does not leave residue in base RAM (but maybe on screen when using sprites / tiles)
|
||
|
Changed: sset() with 2 parameters uses the draw state colour as default
|
||
|
Changed: line() or line(col) can be used to skip drawing and set the (line_x1, line_y1) state on the next call to line(x1,y1)
|
||
|
Changed: vital system functions (load, reboot etc.) can only be overwritten during cartridge execution
|
||
|
Changed: sqrt(x) is now more accurate, and a little faster than x^.5
|
||
|
Changed: sqrt(x) returns 0 for negative values of x
|
||
|
Changed: btnp() delay and repeats now work independently per-button
|
||
|
Changed: pairs(nil) returns an empty function
|
||
|
Changed: Default screenshot scale (now 4x), gif scale (now 3x)
|
||
|
Changed: gif_len now means the length when no start point is specified (used to be the maximum recordable length)
|
||
|
Changed: (Multicarts) When loading data from many different carts, the swap delay maxes out at ~2 seconds
|
||
|
Changed: (Raspberry Pi) removed support for (and dependency on) libsndio
|
||
|
Changed: camera(), cursor(), color(), pal(), palt(), fillp(), clip() return their previous state
|
||
|
Changed: Can not call folder() from a BBS cart running under splore
|
||
|
Changed: F9 resets the video, so that multiple presses results in a sequence of clips that can be joined to together
|
||
|
Changed: color() defaults to 6 (was 0)
|
||
|
Changed: Backed up filenames are prefixed with a timestamp.
|
||
|
Changed: Automatically start on the (host's) current path if it is inside PICO-8's root path
|
||
|
Changed: tostr(x,true) can also be used to view the hex value of functions and tables (uses Lua's tostring)
|
||
|
Changed: Can hold control when clicking number fields (spd, pattern index etc.) to increment/decrement by 4 (was shift)
|
||
|
Fixed: HTML exports running at 60fps sometimes appear to repeatedly speed up and slow down
|
||
|
Fixed: HTML export layout: sometimes broken -- option buttons overlapping in the same place
|
||
|
Fixed: __tostring metatable methods not observed by tostr() / print() / printh()
|
||
|
Fixed: Mac OSX keyboard permissions (fixed in SDL2 0.2.12)
|
||
|
Fixed: Audio mixer: SFX with loop_end > 32 would sometimes fail to loop back
|
||
|
Fixed: btn() firing a frame late, and not on the same frame as stat(30)
|
||
|
Fixed: #include can not handle files saved by some Windows text editors in default format (w/ BOM / CRLF)
|
||
|
Fixed: Exports do not flatten #include'd files
|
||
|
Fixed: Default window size has too much black border (now reverted to previous default)
|
||
|
Fixed: Functions yielded inbetween frames occasionally push an extra return value (type:function) to the stack
|
||
|
Fixed: can't load png-encoded carts with code that starts with a :
|
||
|
Fixed: .gif output unnecessarily large
|
||
|
Fixed: .gif recording skipping frames when running at 15fps
|
||
|
Fixed: printh does not convert to unicode when writing to console or to a file
|
||
|
Fixed: cart data sometimes not flushed when loading another cart during runtime
|
||
|
Fixed: Can not navigate patterns with -,+ during music playback
|
||
|
Fixed: Mouse cursor not a hand over some buttons
|
||
|
Fixed: Laggy mouseover messages (e.g. showing current colour index, or map coordinates)
|
||
|
Fixed: Can't paste glyphs into search field
|
||
|
Fixed: Tab spacing always jumps config.tab_spaces instead of snapping to next column
|
||
|
Fixed: -p switch name is wrong (was only accepting "-param" in 0.12.*
|
||
|
Fixed: Code editor highlighting goes out of sync after some operations
|
||
|
Fixed: Multicart communication problem (affecting PICOWARE)
|
||
|
Fixed: time() speeds up after using the RESUME command
|
||
|
Fixed: Audio state is clobbered when using the RESUME command
|
||
|
Fixed: Audio glitch when fading out music containing slide effect (1)
|
||
|
Fixed: Toggling sound from splore cart->options menu has no effect
|
||
|
Fixed: Devkit keyboard works when paused
|
||
|
Fixed: "-32768 % y" gives wrong results
|
||
|
Fixed: Replacing all text in code editor breaks undo history
|
||
|
Fixed: Double click to select last word in code does not include the last character
|
||
|
Fixed: Weird block comment behavior in code editor
|
||
|
Fixed: HTML export: cart names can not contain quotes
|
||
|
Fixed: HTML export: menu button layout under chromium
|
||
|
Fixed: HTML export: Adding content above cartridge breaks mobile layout
|
||
|
Fixed: HTML export: Can touch-drag PICO-8 screen around (breaks simulated mouse input)
|
||
|
Fixed: LOAD("#ABC") does not always immediately yield
|
||
|
Fixed: Infinite RUN() loop crashes PICO-8
|
||
|
Fixed: Mouse cursor is not a finger on top of most "pressable" button-style elements
|
||
|
Fixed: CD command fails when root_path is relative (e.g. "pico8 -root_path .")
|
||
|
Fixed: poke in fill pattern addresses (0x5f31..0x5f33) discards some bits
|
||
|
Fixed: After using ctrl-click in map editor, can not modify map outside that region
|
||
|
Fixed: Shift-selecting sprites from bottom right to top left selects wrong region
|
||
|
Fixed: Changing GIF_LEN from PICO-8 commandline sometimes breaks gif saving
|
||
|
Fixed: pget() sometimes returns values with high bits set
|
||
|
Fixed: Preprocessor: unary operator lhs is not separated in some cases (e.g. x=1y+=1)
|
||
|
Fixed: Preprocessor: ? shorthand prevents other preprocess replacements on same line
|
||
|
Fixed: Preprocessor: fails when multiple shorthand expressions + strings containing brackets appear on the same line
|
||
|
Fixed: Loading a .p8 file with too many tabs discards the excess code.
|
||
|
Fixed: Map editor's stamp tool wraps around when stamping overlapping the right edge.
|
||
|
Fixed: Very quick/light tap events sometimes do not register
|
||
|
Fixed: SFX tracker mode: can't copy notes with shift-cursors before clicking (whole sfx is copied instead)
|
||
|
Fixed: "..." breaks syntax highlighting
|
||
|
Fixed: Click on text, press up/down -> cursor reverts to previous horizontal position
|
||
|
Fixed: CTRL-[a..z] combinations processed twice under some linux window managers
|
||
|
Fixed: ctrl-up/down to jump to functions in the code editor breaks when "function" is followed by a tab
|
||
|
Fixed: map & gfx drawing selection is not applied consistently between tools
|
||
|
Fixed: Using right mouse button to pick up a colour / tile value sometimes also applies current tool
|
||
|
|
||
|
|
||
|
v0.1.12c
|
||
|
|
||
|
Fixed: CPU usage reported by stat(1) is higher than actual value
|
||
|
Fixed: Fail to load .p8 cartridges w/ BOM marker / CRLF endlines
|
||
|
Fixed: Syntax errors / crash caused by #including files containing BOM / CRLFs
|
||
|
Fixed: Can not save .p8 when contains unresolved #includes
|
||
|
Fixed: Can't open pico-8.txt in Notepad.exe (added CRLFs)
|
||
|
Fixed: Can delete null terminator at end of code (revealing previously deleted code)
|
||
|
|
||
|
|
||
|
v0.1.12b
|
||
|
|
||
|
Added: config command (e.g. CONFIG THEME CLASSIC)
|
||
|
Fixed: Windows sound resampling artifacts (moved to SDL2 2.0.9 audio:directsound)
|
||
|
Fixed: Glyphs stored as unicode can not load when #include'd
|
||
|
Fixed: Code highlighting is wrong after select and delete a line
|
||
|
Fixed: Last line endpoint not present in draw state memory
|
||
|
Fixed: Ubuntu 16.04 can not run because requires glibc 2.27 (reduced dependency to 2.14)
|
||
|
Fixed: stat(102) returns nil when run from binary instead of 0 (now 0)
|
||
|
Fixed: Loading cartridge from commandline fails when path contains "../"
|
||
|
Fixed: (OSX) Crash when reloading external changes with CTRL-R
|
||
|
Fixed: (Windows) Crash when running cart with included code
|
||
|
Fixed: Can not export or include extra cartridges outside of current directory
|
||
|
Fixed: Off by 1 when search for line 1 (affected ctrl-b, ctrl-l)
|
||
|
Fixed: html template -- mouse cursor showing over canvas (now hidden by default)
|
||
|
|
||
|
|
||
|
v0.1.12
|
||
|
|
||
|
Added: #include a text file, or a tab from another cartridge
|
||
|
Added: Unlimited undo for gfx,map,sfx
|
||
|
Added: [sfx] snippets: copy and paste sound & music between PICO-8 instances and BBS posts
|
||
|
Added: (BBS) sfx snippet player
|
||
|
Added: CTRL-G in code editor to repeat search across all tabs
|
||
|
Added: Splore search text entry with cursor key button presses
|
||
|
Added: Custom tab widths (tab_width in config.txt)
|
||
|
Added: Web exporter template: joystick & touch support, preview image, menu buttons, adaptive size, controls screen
|
||
|
Added: .wasm exporter (use -w)
|
||
|
Added: Raspberry Pi binary exporter
|
||
|
Added: -export // run the EXPORT command from host commandline
|
||
|
Added: Toggle flags on multiple sprites at once by selecting them first
|
||
|
Added: Confirmations when loading/saving with unsaved changes
|
||
|
Added: Windowed mode support for Raspberry Pi
|
||
|
Added: serial() interface for Raspberry Pi // serial() -- spi, ws281x, direct bit banging // 0.2.1 update: dropped spi
|
||
|
Added: api: peek2 poke2 rawset rawget rawlen rawequal next
|
||
|
Added: Comment/uncomment selected block with CTRL-B
|
||
|
Added: Can save screenshots and gifs from exported binaries via EXTCMD
|
||
|
Added: Can exit exported binaries after runtime error / stop(), and also via EXTCMD("SHUTDOWN")
|
||
|
Added: SHUTDOWN menu item added to pause menu when running via "-run cartfile"
|
||
|
Added: -kiosk to run in kiosk mode: boot into splore, favourites menu only, no cart menu
|
||
|
Added: -root_path to set root cartridges folder from commandline
|
||
|
Added: shift+space in song view to play from the current quarter of the selected channel
|
||
|
Added: CTRL-W, CTRL-E in code editor to jump to start / end of line
|
||
|
Added: -accept_future to load cartides made with future versions of PICO-8
|
||
|
Added: -preblit_scale (default: auto) for less blurry scaling with -pixel_perfect 0
|
||
|
Added: -pixel_perfect -1 (auto) only uses pixel perfect scaling when < 10% of the containing screen axis is wasted
|
||
|
Added: highlight all occurances when searching for text in code editor
|
||
|
Added: tab completion across directories
|
||
|
Added: In map editor, non-zero cels that are drawn all black are marked with a single blue dot
|
||
|
Changed: all(), foreach() cpu cost is now much cheaper (but still a little more than using a for loop)
|
||
|
Changed: cursor() can also set the current color with a third parameter
|
||
|
Changed: stat 24..26 return -1 when no music is playing
|
||
|
Changed: 3x4 font characters (uppercase in ascii) allowed in code editor (but not pasteable/editable)
|
||
|
Changed: time() / t() always means seconds since run (but still updated once per _update() / _update60)
|
||
|
Changed: line(x1,y1) can be used to draw from the end of the last line
|
||
|
Changed: del() returns the item deleted on success
|
||
|
Changed: single setting for audio volume (-volume switch, "volume" in config.txt)
|
||
|
Changed: allow '-' in cartdat() names
|
||
|
Changed: 8 and - only map to buttons 4 and 5 by default for CHIP build
|
||
|
Changed: Raspberry Pi pico8_dyn build does not support gpio/serial (and so does not require wiringPi)
|
||
|
Changed: Default theme is 1 (blue background in code editor)
|
||
|
Changed: When loading a cart from commandline, automatically set the current path if inside PICO-8's filesystem
|
||
|
Fixed: Code editor uses too much cpu / battery power
|
||
|
Fixed: cstore() with an external cart name broken when run from exported cart or as bbs cart
|
||
|
Fixed: Undoing changes to SFX after using pitch drawing tool clears SFX data
|
||
|
Fixed: Running headless scripts under Windows / Mac OSX crashes
|
||
|
Fixed: Running headless scripts with no video driver fails
|
||
|
Fixed: Can not load BBS carts in headless script mode (without auto-running)
|
||
|
Fixed: (Web exporter) mouse cursor doesn't work in fullscreen
|
||
|
Fixed: (Web exporter) mouse button 2 brings up context menu
|
||
|
Fixed: (Web exporter) Clusters of FS.syncfs calls causing error messages (and inefficient?)
|
||
|
Fixed: (Windows) PICO-8 behaves as if it is not the foreground application
|
||
|
Fixed: divide and abs sign flipping for 0x8000.0000
|
||
|
Fixed: sqrt(0x0000.0001) freezes
|
||
|
Fixed: "-1"+0 evaluates to 0xffff.0001
|
||
|
Fixed: shift-tabbing to unindent alters selection range
|
||
|
Fixed: background_sleep_ms reverts to default value
|
||
|
Fixed: "open in thread" option appears for local carts
|
||
|
Fixed: (code editor) undo markers in unexpected places
|
||
|
Fixed: root_path, desktop_path in config.txt doesn't work without trailing slash
|
||
|
Fixed: Audio sampling rate is wrong when device/driver doesn't support 22050MHz
|
||
|
Fixed: Loading cart with less than 5 pixel rows of gfx does not clear default white cross sprite
|
||
|
Fixed: cpu cycle exploit using peek4 with no parameters
|
||
|
Fixed: SFX keyboard editing operations (e.g. SPD +/-) sometimes applied to the wrong SFX
|
||
|
Fixed: Cursor behaviour when moving between song and sfx view, and when playing music
|
||
|
Fixed: Selecting SFX notes with shift + home/end/pgup/pgdown
|
||
|
Fixed: Vibrato (2) and drop (3) effects in SFX instruments not observed
|
||
|
Fixed: Can not place note at C-0 in pitch mode
|
||
|
Fixed: CTRL-F search in code skips matches that are close together
|
||
|
Fixed: (Mac) warning about unoptimized program (built with SDL 2.0.9, + now 64-bit)
|
||
|
Fixed: (Raspberry Pi) Keypresses leaking to desktop
|
||
|
Fixed: (Raspberry Pi) Keyboard layout fixed to US
|
||
|
Fixed: printh(nil) prints [false] instead of [nil]
|
||
|
Fixed: toggling audio mute twice returns to maximum volume
|
||
|
Fixed: alt+cursors moves cursor in code editor
|
||
|
Fixed: del does not work on first character of code or commandline
|
||
|
Fixed: preprocessor breaks on double slash in string s="\\"
|
||
|
Fixed: sometimes code executing a little after point of runtime error
|
||
|
Fixed: Token count reported in editor is more than 0 after rebooting
|
||
|
Fixed: "Removed empty tabs" message displayed when loading cart with fewer tabs
|
||
|
Fixed: Member variables highlighted when same as API function names (e.g. actor.spr)
|
||
|
Fixed: Hot-plugged joysticks not recognized
|
||
|
|
||
|
|
||
|
v0.1.11g
|
||
|
|
||
|
Added: CTRL-C to copy contents of commandline
|
||
|
Added: stat(100..102) for current breadcrumb label, bbs cart id, and hostname (web)
|
||
|
Added: content_filter in config.txt
|
||
|
Added: Cartverse cart id support (not live server-side yet though)
|
||
|
Fixed: Tab preview does not show on mouseover
|
||
|
Fixed: Can't paste uppercase characters into commandline
|
||
|
Fixed: Preprocessor can't handle glyphs in form: "♥.x += 1"
|
||
|
Fixed: Unsaved changes sometimes reported when filename is not set
|
||
|
Fixed: Pause menu doesn't open inside infinite loop inside _draw
|
||
|
Fixed: load() crashes when "parameter string" parameter is not a string
|
||
|
Fixed: cstore(),reload() crash when external cart filename is not a string
|
||
|
Fixed: printh(str, "@clip") fails for glyph characters in str
|
||
|
|
||
|
|
||
|
v0.1.11f
|
||
|
|
||
|
Fixed: Pause menu doesn't open inside an infinite loop
|
||
|
Fixed: Binary and hex string digits outside of 0xffff.ffff alter result
|
||
|
|
||
|
|
||
|
v0.1.11e
|
||
|
|
||
|
Added: stat(30..31) for devkit keyboard input
|
||
|
Added: extcmd("pause") extcmd("reset") extcmd("breadcrumb")
|
||
|
Added: lshr(), ceil(), rotl(), rotr(), peek4(), poke4()
|
||
|
Added: stat(12..15) to grab the position of the pause menu (x0,y0,y1,y1)
|
||
|
Added: DPAD game controller buttons mapped to LRUD
|
||
|
Added: CTRL-click on song navigator to scroll by 4 patterns
|
||
|
Added: Can type and paste glyphs in commandline
|
||
|
Added: Notification when CTRL-R fails to reload because of unsaved changes
|
||
|
Added: Notification when code automatically converted to lower-case
|
||
|
Added: INFO() checks for "external changes" (e.g. when using a separate text editor)
|
||
|
Added: .p8.png format can be used with cstore() and carts bundled in multicarts
|
||
|
Added: Can optionally set fill pattern using colour parameter
|
||
|
Changed: Glyphs can be used as variable names
|
||
|
Changed: Glyphs stored in clipboard and .p8 format as roughly corresponding unicode
|
||
|
Changed: .p8 format skips storing tailing rows of data that match default state
|
||
|
Changed/Fixed: shr(x,n) is now equivalent to calling shr(x,1) n times when n >= 32
|
||
|
Fixed: Error message and stack trace line numbers 0 or slightly out
|
||
|
Fixed: Unclosed block error navigates cursor to <eof> rather than start of block
|
||
|
Fixed: Exported binaries can load carts outside of bundle
|
||
|
Fixed: BBS cart loaded from a local cart loses data cstore()ed during previous run
|
||
|
Fixed: btn() returns same as btnp()
|
||
|
Fixed: btnp(6) always returns false
|
||
|
Fixed: Missing mask pixels in cart download animation frame
|
||
|
Fixed: Crash when try to load a directory as a cart
|
||
|
Fixed: Sometimes cursor position set by keyboard mouse emulation in code editor
|
||
|
|
||
|
|
||
|
v0.1.11d
|
||
|
|
||
|
Added: t() aliased to time()
|
||
|
Fixed: time() always returns 0 when there is no _update function
|
||
|
Fixed: (raspi) Keyboard stops responding after pressing CTRL-F, CTRL-Z
|
||
|
Fixed: (raspi) Double keypresses in sound editor when entering notes
|
||
|
Fixed: stat(6) pads parameter string with spaces
|
||
|
|
||
|
|
||
|
v0.1.11c
|
||
|
|
||
|
Added: Local and UT time queries using stat()
|
||
|
Added: host_framerate_control (config.txt) to improve performance on slower machines and web
|
||
|
Added: Control over cpu usage when running in background (-background_sleep_ms / config.txt)
|
||
|
Added: Windows icon in exported exe
|
||
|
Added: F11 to toggle fullscreen
|
||
|
Added: export -c switch to indicate transparent icon colour
|
||
|
Added: show_backup_messages (config.txt) to turn off backup notifications
|
||
|
Added: SFX instruments documentation in pico8.txt
|
||
|
Added: Error message when trying to export carts with code size over the compressed limit
|
||
|
Changed: If config.txt is not found, the same directory as the executable is searched
|
||
|
Changed: If sdl_controllers.txt exists in the same directory as the executeable, it is processed first
|
||
|
Changed: Shorthand if () statements must be written on a single line
|
||
|
Fixed: reload() from bundled, non-primary cart in exported html multicart reads only original data
|
||
|
Fixed: Exported binaries wrongly observe F7 (capture label)
|
||
|
Fixed: Loading carts from earlier versions alters SFX data not intended for audio
|
||
|
Fixed: Old version of fill patterns documentation near end of pico8.txt
|
||
|
Fixed: 'backed up unsaved changes' message displayed during runtime for cstored() carts
|
||
|
Fixed: PICO-8 runs too slowly when in background (new default background_sleep_ms: 20)
|
||
|
Fixed: Saving screenshots and videos from exported binaries are named 0_*
|
||
|
Fixed: Compressed size limit warning on save doesn't mention exported carts
|
||
|
Fixed: btn(), btnp() don't work in infinite loops
|
||
|
Fixed: btnp() timing inconsistent between 30fps / 60fps / during frame-skipping / with no _update
|
||
|
Fixed: Can't move between channels while music is playing in song mode
|
||
|
|
||
|
|
||
|
v0.1.11b
|
||
|
|
||
|
Fixed: Preprocessor bug regressions: "if (..) or", "a.b -= c - d"
|
||
|
Fixed: Crash when pressing menu button on an empty favourites list
|
||
|
|
||
|
|
||
|
v0.1.11
|
||
|
|
||
|
Added: Binary exporters (Windows, Linux, Mac OSX)
|
||
|
Added: Code tabs
|
||
|
Added: Splore cart menu
|
||
|
Added: Fill patterns
|
||
|
Added: Custom sfx instruments
|
||
|
Added: load("#1234") to load [and run] a BBS cart
|
||
|
Added: -x switch // execute a cart headless, for making commandline toolchains
|
||
|
Added: Compressed size display and limit warning lights in code editor
|
||
|
Added: CTRL-L to jump to a line number in code editor
|
||
|
Added: numbers can be written in binary: 0b10100010
|
||
|
Added: tostr(), tonum()
|
||
|
Added: extcmd(): audio_rec, audio_end to record all audio output.
|
||
|
Added: ls() returns a list of local files if called while running
|
||
|
Added: getmetatable()
|
||
|
Added: coroutine error reporting // wrap coresume() in assert()
|
||
|
Added: sfx() can take a 4th parameter: number of notes to play
|
||
|
Added: Live sfx and music editing + better navigation controls
|
||
|
Added: Transpose selected sfx notes relative to C by entering a note w/ SHIFT held
|
||
|
Added: Insert and delete sfx rows with enter and backspace
|
||
|
Added: Hidden note data is shown in sfx editor when relevant (slide, arps)
|
||
|
Added: Warning displayed when unsaved changes backed up
|
||
|
Added: Separate animation for downloading vs. loading a cart
|
||
|
Added: export -p switch to supply a customized html template
|
||
|
Added: Mousewheel when devkit mouse enabled: stat(36) // not supported in web
|
||
|
Added: < > to change zoom level in gfx and map editors
|
||
|
Changed: Rebalanced / fixed api cpu costs
|
||
|
Changed: Screenshot and gif filenames based on current cart if available
|
||
|
Changed: add() returns the added object
|
||
|
Changed: removed global hpf on audio
|
||
|
Changed: (sfx) can slide to volume 0
|
||
|
Changed: removed master low pass filter
|
||
|
Changed: assert() can take an optional error_message parameter
|
||
|
Changed: ? (shorthand for print()) can be prefixed by whitespace
|
||
|
Changed: shl(), shr() return 0 if second parameter >= 32
|
||
|
Changed: Automatically drop down to software blitting mode if opengl fails
|
||
|
Changed: Lua memory limit set to 2MB (was 1MB)
|
||
|
Changed: Some options (-width, -show_fps) apply only to the session; not saved to config.txt
|
||
|
Updated: Internal game controller mappings from SDL_GameControllerDB
|
||
|
Fixed: Pops & clicks in audio when switching between playing SFX
|
||
|
Fixed: Crash in audio mixer because of bad locking
|
||
|
Fixed: Crash when loading .p8 files with more than 64k of code
|
||
|
Fixed: Indexing of sparse tables fails after removing n/2 elements
|
||
|
Fixed: Calling stat() inside an infinite loop crashes
|
||
|
Fixed: Resetting cartridge corrupts cartridge data in range 0x5e00..0x5eff
|
||
|
Fixed: Can not recover from a cart error caused by glitchy data on resetting
|
||
|
Fixed: String->negative number conversion off by 0x0.0001 (-1 --> 0xffff0001)
|
||
|
Fixed: Crash when running cart closed to 64k char limit
|
||
|
Fixed: Cursor can't move to the right of last character in code editor
|
||
|
Fixed: Missing highlighted keywords: in, add, del, menuitem
|
||
|
Fixed: Preprocessor bugs: "a+=1+2\n*3", "a+=(1)ba=42", "a[(1)]+=1"
|
||
|
Fixed: Preprocessor performs replacements inside a string printed with ?
|
||
|
Fixed: Display freezes when terminating a program running at >100% cpu
|
||
|
Fixed: Quick-running (CTRL-R) clobbers some editor state (e.g. current sprite page)
|
||
|
Fixed: Loading a .p8 file with a future version reports a generic failure
|
||
|
Fixed: alt-enter to toggle fullscreen also triggers pause menu
|
||
|
Fixed: Splore scrolling jumps around when list gets too long
|
||
|
|
||
|
|
||
|
v0.1.10c
|
||
|
|
||
|
Fixed: atan flips sign for very negative values of x close to zero
|
||
|
|
||
|
|
||
|
v0.1.10b
|
||
|
Fixed: HTML exporter carts don't run
|
||
|
Fixed: HTML export 60fps support broken
|
||
|
Fixed: HTML export when path has a space in it (common for OSX)
|
||
|
Fixed: atan2 ignores sign of y
|
||
|
Fixed: (Raspberry Pi) Crash when access gpio not as root
|
||
|
|
||
|
|
||
|
v0.1.10
|
||
|
|
||
|
Added: Multi-cart export in html
|
||
|
Added: Cart reset glitch
|
||
|
Added: Demo carts: bounce, sort
|
||
|
Added: .p8 format can now store cart labels
|
||
|
Added: Splore navigation keys: pageup/down, home, end
|
||
|
Added: Splore usage hint shown on empty favourites list
|
||
|
Added: Warning on boot when data folder is read-only or can't be created
|
||
|
Added: Pressing tab with code selected indents those lines (shift-tab to un-indent)
|
||
|
Added: Double click word to select it
|
||
|
Added: Trigger screenshot/video/label capture from inside program: extcmd()
|
||
|
Changed: CTRL+left/right in code editor skips to end of word or span of non-whitespace
|
||
|
Changed: When a cart terminates from splore, button press is required to continue
|
||
|
Changed: load("@clip") can only be called from commandline (security)
|
||
|
Fixed: Can over-allocate host memory if exceed it within one frame
|
||
|
Fixed: atan2(-1, -32768) crash, and error for small values of dy
|
||
|
Fixed: (Web) using cstore() on self causes unloadable cart (bug introduced in 0.1.8?)
|
||
|
Fixed: (web) Pressing ctrl-v crashes the player (should do nothing)
|
||
|
Fixed: (Raspberry Pi) WiringPi library required in static build
|
||
|
Fixed: (Raspberry Pi) Crash on exit when launching via desktop icon
|
||
|
Fixed: (Raspberry Pi) keyboard input broken (observed on raspi2s)
|
||
|
|
||
|
|
||
|
v0.1.9b
|
||
|
|
||
|
Added: Alternative function key mapping: ctrl-6..9 for F6..F9
|
||
|
Added: Alternative glyph entry method: (ctrl-k) to toggle glyph mode
|
||
|
Changed: Enter glyphs with shift a..z, but can be disabled in config.txt
|
||
|
Changed: Increased emscripten ram to 128MB (some carts at risk of running out)
|
||
|
Fixed: Crash when window size is tiny or minified
|
||
|
Fixed: Crash on toggling fullscreen mode
|
||
|
Fixed: printh can write files outside filetree (security issue)
|
||
|
Fixed: show_fps (can also now be toggled with ctrl-1)
|
||
|
Fixed: Shorthand if/then syntax error when using the form: (functionname)(param)
|
||
|
Fixed: log.txt not saved in path specified by -home switch
|
||
|
Fixed: Default application data folder created even when -home specified
|
||
|
Fixed: Missing dynamic builds (pico8_dyn) from linux archives
|
||
|
Fixed: Removed unneeded RPATH from linux binaries
|
||
|
Fixed: export foo%d.wav fails to write multiple files
|
||
|
|
||
|
v0.1.9
|
||
|
|
||
|
Added: Copy and paste sprites and whole cartridges directly to BBS posts
|
||
|
Added: JAM category in splore
|
||
|
Added: GPIO support for Raspberry Pi
|
||
|
Added: Read clipboard using stat(4) after user presses CTRL-V
|
||
|
Added: printh() can optionally write to a file or the host clipboard
|
||
|
Added: Editor tool information and tips shown on mouseover
|
||
|
Added: Set desktop path with -desktop (screenshots and gifs are saved here)
|
||
|
Added: Warning on saving .p8 when compressed code size exceeds .p8.png limit
|
||
|
Added: Alternative editor colours // config.txt: gui_theme 1
|
||
|
Added: Dotted line every 8 rows in song view
|
||
|
Added: -screenshot_scale (default: 3) and -gif_scale (default: 2)
|
||
|
Added: Can use ctrl-up, ctrl-down to jump to start and end of code
|
||
|
Added: CTRL-M to mute/unmute sound
|
||
|
Added: HTML5-exported carts support 60fps
|
||
|
Added: Timeout switch for splore downloads: -timeout
|
||
|
Changed: Glyph characters typed with alt + a..z
|
||
|
Changed: stat(0) does not include allocations waiting to be garbage collected
|
||
|
Changed: Unfiltered screen stretching at integer scales by default
|
||
|
Changed: Removed -aspect and -scale settings (use draw_rect instead)
|
||
|
Fixed: -home has no effect under Windows
|
||
|
Fixed: Sometimes frame skipping starts before CPU usage has reached 100%
|
||
|
Fixed: Double-speed BTNP() timing in 60fps mode
|
||
|
Fixed: Exported HTML fails when _update60 is used instead of _update
|
||
|
Fixed: Can't copy and paste button glyphs
|
||
|
Fixed: Lines containing glyphs do not scroll far enough horizontally
|
||
|
Fixed: Loading .p8 renamed as .p8.png from splore freezes
|
||
|
Fixed: Bucketfill in map doesn't sync to shared memory
|
||
|
Fixed: fset fails when de-setting flags
|
||
|
Fixed: Syntax error when beginning with the form: IF (..) [OR|AND]\n
|
||
|
Fixed: cls() costs twice as much cpu as it should
|
||
|
Fixed: wav file exporter missing some data / writing truncated buffers
|
||
|
Fixed: Entering new notes in song view doesn't observe current volume, instrument
|
||
|
Fixed: alt-tab sometimes generates alt character text entry event
|
||
|
Fixed: Resuming a cancelled download in splore causes crash
|
||
|
Fixed: Controller attributes in log.txt always shown as -1
|
||
|
|
||
|
|
||
|
v0.1.8
|
||
|
|
||
|
Added: 60fps support
|
||
|
Added: Music exporter
|
||
|
Added: Custom GIF length (maximum 120 seconds)
|
||
|
Added: -,+ to navigate sprite tabs, sfx, music patterns
|
||
|
Added: sfx editor: navigate with home, end, pageup/down, mousewheel
|
||
|
Added: <, > to modify sfx speed, or click and drag
|
||
|
Added: Middle mouse button to pan around spritesheet / map
|
||
|
Added: Shortcut command for splore: S
|
||
|
Added: Pre-installed selection of BBS cart (use INSTALL_GAMES)
|
||
|
Added: Warning when saving .p8.png with no label
|
||
|
Added: (OSX) logging to ~/Library/Logs (viewable with Console.app)
|
||
|
Added: -pixel_perfect switch (on by default)
|
||
|
Added: -draw_rect switch
|
||
|
Changed: Can not CTRL-S save over a loaded bbs cart
|
||
|
Changed: Only .p8 files listed by dir() and by splore
|
||
|
Changed: Command history increased to 256
|
||
|
Changed: exit() / shutdown() have no effect while running cart
|
||
|
Fixed: Memory usage (stat(0)) inconsistent across host platforms
|
||
|
Fixed: Spinny disks shows when reloading current cart with load()
|
||
|
Fixed: GIF saver does not respect 64x64 / mirrored modes
|
||
|
Fixed: Miscellaneous multi-line comments / strings issues
|
||
|
Fixed: Empty map cels cost cpu in mapdraw()
|
||
|
Fixed: mapdraw() slowdown when drawing bottom half of map
|
||
|
Fixed: preprocess changes semantics when += and : operators on same line
|
||
|
Fixed: Identifiers starting with underscore counted as extra token
|
||
|
Fixed: Saving .png exceeding compressed code limit fails silently
|
||
|
Fixed: Right-clicking a sprite does not set the currently edited sprite
|
||
|
Fixed: (Windows) extra space added to pasted lines
|
||
|
Fixed: spr() expensive when drawn with low negative coordinates
|
||
|
Fixed: pipe character identical to colon character
|
||
|
Fixed: (Raspberry Pi) shift key appends a character when entering text
|
||
|
Fixed: Editor mode buttons are still clickable during cart runtime
|
||
|
Fixed: When loading a .p8.png file, label is reset and needs to be re-captured
|
||
|
Fixed: export() does not report failure
|
||
|
Fixed: mset()'d changes in shared memory not readable via peek() / sget()
|
||
|
Fixed: cstore() saving edited code
|
||
|
Fixed: audio pop between patterns during music playback
|
||
|
|
||
|
v0.1.7
|
||
|
|
||
|
Added: menuitem()
|
||
|
Added: button glyphs in code (shift-L, R, U, D, X, O)
|
||
|
Added: Customisable data directory (e.g. pico8 -home mydata)
|
||
|
Added: Web gpio pins: read and write pico8_gpio[] in javscript
|
||
|
Fixed: SPLORE search doesn't reset
|
||
|
Fixed: Splore skipping 33rd cart listing after loading more items
|
||
|
Fixed: Crash when selecting a local binary file in splore
|
||
|
Fixed: Semicolon can't be used as a list or statement separator
|
||
|
Fixed: Exported html can not cstore self
|
||
|
|
||
|
|
||
|
v0.1.6
|
||
|
|
||
|
Added: SPLORE local & bbs cartridge explorer
|
||
|
Added: setmetatable(), cocreate(), coresume(), costatus(), yield()
|
||
|
Added: Spinning cart icon to show when a cart is swapped / written to
|
||
|
Added: Permanent storage when carts played in a browser
|
||
|
Added: Adjustable aspect ratio (-aspect 420 for 1:1)
|
||
|
Changed: Lua memory limit: 1024k (was 512k)
|
||
|
Changed: Music channel now resumes after being clobbered by an sfx
|
||
|
Changed: Arpeggios double speed when SFX speed <= 8
|
||
|
Changed: Exceeding compressed code limit does not block saving in .p8 format
|
||
|
Changed: spr() half as expensive, to be consistent with map()
|
||
|
Changed: Fractional hex number notation: 0x0.3 == 0x0.3000, (was 0x0.0003)
|
||
|
Changed: : operator doesn't count as an extra token (same as .)
|
||
|
Changed: cstore() writes directly to disk
|
||
|
Changed: cstore(), reload() return number of bytes read / written
|
||
|
Changed: save() while running does nothing. (use cstore() instead)
|
||
|
Changed: load() while running loads and runs the specified cartridge
|
||
|
Fixed: Small pops in audio mixer caused by sound wave discontinuities
|
||
|
Fixed: HTML5-exported sound clicks badly under Chrome
|
||
|
Fixed: Display palette is not oberserved when exporting GIFs
|
||
|
Fixed: Rapid keypresses causes duplicate readings in tracker & text editor
|
||
|
Fixed: += inside comments breaks preprocessor
|
||
|
Fixed: sspr() cpu cost the same when clipped
|
||
|
Fixed: cartdata() with bad parameters crashes
|
||
|
Fixed: EXPORT from commandline can not be used without brackets and quotes
|
||
|
|
||
|
|
||
|
v0.1.5
|
||
|
|
||
|
Added: Raspberry Pi Build
|
||
|
Added: Keyboard configuration for player buttons (KEYCONFIG)
|
||
|
Added: Music tracker select / copy / paste
|
||
|
Added: Single-level undo in audio tools
|
||
|
Added: Live preview of frequencies in sound editor
|
||
|
Fixed: Command history extends past last reboot
|
||
|
Fixed: Sfx exporter broken
|
||
|
Fixed: Slashes at end of path resolve to double slashes
|
||
|
Fixed: Load cart from commandline under Windows
|
||
|
|
||
|
|
||
|
v0.1.4d
|
||
|
v0.1.4c
|
||
|
|
||
|
Fixed: International character entry inserting extra characters
|
||
|
Fixed: Lines with tabs have broken cursor placement and display boundary
|
||
|
|
||
|
v0.1.4b
|
||
|
|
||
|
Fixed: OSX command-key combinations broken
|
||
|
|
||
|
v0.1.4
|
||
|
|
||
|
Added: spritesheet importing and exporting with import("blah.png"), export("blah.png")
|
||
|
Added: sfx exporting with export("blah%d.wav")
|
||
|
Added: External cartridge parameter for reload() and cstore()
|
||
|
Added: Persistent cartridge data mapped to 0x5e00
|
||
|
Added: Click token limit to toggle token & char limit display
|
||
|
Added: assert(), type()
|
||
|
Added: P to pause
|
||
|
Changed: code char limit: 64k (was 32k)
|
||
|
Changed: local declarations and semicolons not counted as tokens
|
||
|
Changed: Pairs of brackets and block delimitations count as one token
|
||
|
Changed: Only _update() or _draw() need to exist to enter main loop
|
||
|
Changed: Allow forward-slash in code editor
|
||
|
Changed: info() reports current (last loaded or saved) filename
|
||
|
Changed: html5 version compiled with NO_DYNAMIC_EXECUTION
|
||
|
Changed: can only cstore up to 64 different files in one session
|
||
|
Changed: load() automatically copies data section of cart to base ram
|
||
|
Fixed: Shift-drag-copy sprites -> paste only pastes 1x1
|
||
|
Fixed: ".." should count as one token
|
||
|
Fixed: Tracker displaying D instead of .
|
||
|
Fixed: Multi-line comments
|
||
|
Fixed: Crash on run when code close to char limit
|
||
|
Fixed: When over token limit, can not run any command
|
||
|
Fixed: Unused high bits in SFX section not saved in .p8 format
|
||
|
Fixed: Camera position memory mapping out of sync
|
||
|
Fixed: pico8.txt link broken in windows installer
|
||
|
Fixed: print() crashes when parameter is not a string or numbers
|
||
|
Fixed: Multi-line strings & escape chars mess up tokenizer and print()
|
||
|
Fixed: Joystick not responding when left stick is up to the left
|
||
|
Fixed: Alt-F4 saves screenshot before quitting
|
||
|
Fixed: Sprite editor mode button doesn't show fullscreen mode
|
||
|
Fixed: -sound parameter not working in html5 version
|
||
|
|
||
|
|
||
|
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 bitwise 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 display 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: Hexadecimal 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: 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
|
||
|
|
||
|
|
||
|
|