PICO-8 Wiki
(fix the order of the flags for each music pattern)
Tag: Visual edit
(passive voice is preferable in wiki articles)
(28 intermediate revisions by 8 users not shown)
Line 1: Line 1:
Pico-8 has 32 kilobytes of addressable memory, used for graphics, map, sound, music, and direct access to hardware features such as persistent cartridge data and GPIO pins. Programs can read from and write to this data using [[Peek|<code>peek()</code>]] and [[Poke|<code>poke()</code>]].
+
PICO-8 has 32 kilobytes of addressable memory, used for graphics, map, sound, music, and direct access to hardware features such as persistent cartridge data and GPIO pins. Programs can read from and write to this data using [[Peek|<code>peek()</code>]] and [[Poke|<code>poke()</code>]].
   
While many games can use the built-in functions for graphics and sound, memory access enables advanced techniques such as repurposing memory regions or generating graphics and sound data algorithmically. For features such as the GPIO pins, [[Peek|<code>peek</code>()]] and [[Poke|<code>poke()</code>]] are currently the only way to access the feature.
+
While many games can use the built-in functions for graphics and sound, memory access enables advanced techniques such as repurposing memory regions or generating graphics and sound data algorithmically. For features such as the GPIO pins, [[Peek|<code>peek()</code>]] and [[Poke|<code>poke()</code>]] are currently the only way to access the feature.
   
 
The first 16 kilobytes are copied from the cartridge into memory when the cartridge is loaded. When the cartridge changes a value in memory, it is only changed in memory and not in the cartridge itself.
 
The first 16 kilobytes are copied from the cartridge into memory when the cartridge is loaded. When the cartridge changes a value in memory, it is only changed in memory and not in the cartridge itself.
   
You can use the [[Cstore|<code>cstore()</code>]] function to write memory data to the cartridge file. You can also use the [[Reload|<code>reload()</code>]] function to load cartridge data back into memory, or load a region of memory from another cartridge file.
+
The [[Cstore|<code>cstore()</code>]] function can be used to write memory data to the cartridge file. The [[Reload|<code>reload()</code>]] function can also be used to load cartridge data back into memory, or load a region of memory from another cartridge file.
   
 
The Lua program stack (variables, etc.) is not stored in addressable memory and cannot be accessed directly by the program.
 
The Lua program stack (variables, etc.) is not stored in addressable memory and cannot be accessed directly by the program.
Line 54: Line 54:
   
 
The bottom half of the sprite sheet and the bottom half of the map region overlap in memory. Typically, a game uses this region for only one purpose or the other.
 
The bottom half of the sprite sheet and the bottom half of the map region overlap in memory. Typically, a game uses this region for only one purpose or the other.
  +
  +
'''0x0000-0x0fff / 0-4095'''
  +
:The upper 64 rows in the sprite sheet. Each 64-byte row contains 128 pixels. Each byte contains two adjacent pixels, with the lo 4 bits being the left/even pixel and the hi 4 bits being the right/odd pixel.
  +
  +
'''0x1000-0x1fff / 4096-8191'''
  +
:The lower 64 rows in the sprite sheet. Same format as above. Overlaps ''lower'' half of Map (see below).
   
 
== Map ==
 
== Map ==
Line 60: Line 66:
   
 
The map is read from left to right, top to bottom order.
 
The map is read from left to right, top to bottom order.
  +
  +
'''0x1000-0x1fff / 4096-8191'''
  +
:The ''lower'' 32 rows of the map. Each row contains 128 tiles. Each byte contains one tile index. Overlaps lower half of Sprite Sheet (see above).
  +
  +
'''0x2000-0x2fff / 8192-12287'''
  +
:The upper 32 rows of the map. Each row contains 128 tiles. Each byte contains one tile index.
   
 
== Sprite flags ==
 
== Sprite flags ==
Line 66: Line 78:
   
 
In the graphics editor, the flags are arranged left to right from LSB to MSB: red=1, orange=2, yellow=4, green=8, blue=16, purple=32, pink=64, peach=128.
 
In the graphics editor, the flags are arranged left to right from LSB to MSB: red=1, orange=2, yellow=4, green=8, blue=16, purple=32, pink=64, peach=128.
  +
  +
'''0x3000-0x30ff / 12288-12543'''
  +
:Each byte represents the flags for the associated sprite.
   
 
== Music ==
 
== Music ==
Line 81: Line 96:
 
The effect speed is a value between 0 and 255, representing the duration of each note in the effect, as a multiple of 1/128 seconds. Using the full effect length of 32 notes, with a speed of 1, the full effect plays in 1/4 second. With a speed of 4, the full effect plays in 1 second.
 
The effect speed is a value between 0 and 255, representing the duration of each note in the effect, as a multiple of 1/128 seconds. Using the full effect length of 32 notes, with a speed of 1, the full effect plays in 1/4 second. With a speed of 4, the full effect plays in 1 second.
   
In an effect used for a music pattern, you can calculate beats per minute based on how many notes per "beat." For example, if an effect plays a "beat" every four notes in an effect, a speed of 15 is equivalent to 15/128 seconds per note, 15*4/128 seconds per four notes (one beat), (15*4)/(128*60) minutes per beat, or (128*60)/(15*4) = 128 beats per minute.
+
In an effect used for a music pattern, beats per minute can be calculated based on how many notes per "beat." For example, if an effect plays a "beat" every four notes in an effect, a speed of 15 is equivalent to 15/128 seconds per note, 15*4/128 seconds per four notes (one beat), (15*4)/(128*60) minutes per beat, or (128*60)/(15*4) = 128 beats per minute.
   
Each note is encoded in 16 bits, least significant byte first, like so:
+
Each note is encoded in 16 bits, in [https://en.wikipedia.org/wiki/Endianness Little Endian] style, with the low 8 bits in the first byte, and the hi 8 bits in the second, formatted like so:
   
  +
<div align=center>
<code>w2-w1-pppppp c-eee-vvv-w3</code>
 
  +
{| class="article-table" style="display: inline-table;"
  +
!colspan=8 align=center|Second byte / Hi 8 bits
  +
|-
  +
|c
  +
|e
  +
|e
  +
|e
  +
|v
  +
|v
  +
|v
  +
|w
  +
|}
  +
{| class="article-table" style="display: inline-table;"
  +
!colspan=8 align=center|First byte / Lo 8 bits
  +
|-
  +
|w
  +
|w
  +
|p
  +
|p
  +
|p
  +
|p
  +
|p
  +
|p
  +
|}
  +
</div>
   
 
* <code>c</code>: when c is 1, waveform is a custom instrument corresponding to sfx 0-7; otherwise it is one of the eight built-in waveforms (PICO-8 0.1.11+)
 
* <code>eee</code>: effect (0-7)
 
* <code>eee</code>: effect (0-7)
 
* <code>vvv</code>: volume (0-7)
 
* <code>vvv</code>: volume (0-7)
* <code>w3w2w1</code>: waveform (0-7)
+
* <code>www</code>: waveform (0-7)
 
* <code>pppppp</code>: pitch (0-63)
 
* <code>pppppp</code>: pitch (0-63)
  +
* <code>c</code>: when c is 1, waveform is a custom instrument corresponding to sfx 0-7; otherwise it is one of the eight built-in waveforms (Pico-8 0.1.11)
 
  +
For example, a note's pitch and effect can be seen using <code>peek(0x3200 + 68*track + 2*time)</code>, and instrument and volume by <code>peek(0x3200 + 68*track + 2*time + 1)</code>. So if 30 was seen for instrument and volume, they are stored in bits <code>0b0011110</code> so the instrument is <code>0b001</code> (1) and volume is <code>0b111</code> (7); the last bit is used for sfx instrument flag, 0 if off, 1 if on. <!-- TODO: This bit really needs to be re-worded. It's kind of hard to follow. -->
   
 
== General use ==
 
== General use ==
   
  +
'''0x4300-0x5dff / 17152-24063'''
The memory region from 0x4300 to 0x5dff is available for the program to use for any purpose.
+
This memory region is available for the program to use for any purpose.
   
This region is not loaded from the cartridge, though you can use the [[Reload|<code>reload()</code>]] function to copy data into this region from a cartridge file.
+
This region is not loaded from the cartridge, though the [[Reload|<code>reload()</code>]] function can be used to copy data into this region from a cartridge file.
  +
  +
(Undocumented?) This region is not reset when loading another cart via [[Load|load()]], so can be used for passing data to and from the loaded cart.
   
 
== Persistent cart data ==
 
== Persistent cart data ==
   
  +
'''0x5e00-0x5eff / 24064-24319'''
After persistent data is initialized with the [[Cartdata|<code>cartdata()</code>]] function, the 256-byte region from 0x5e00 to 0x5eff represents the 64 number values accessible by [[Dset|<code>dset()</code>]] and [[Dget|<code>dget()</code>]]. These numbers are stored in the same 4-byte, little endian, 16.16 fixed-point format used by [[Peek4|<code>peek4()</code>]] and [[Poke4|<code>poke4()</code>]].
+
After persistent data is initialized with the [[Cartdata|<code>cartdata()</code>]] function, the 256-byte region from 0x5e00 to 0x5eff represents the 64 number values accessible by [[Dset|<code>dset()</code>]] and [[Dget|<code>dget()</code>]]. These numbers are stored in the same 4-byte, [https://en.wikipedia.org/wiki/Endianness little endian], 16.16 fixed-point format used by [[Peek4|<code>peek4()</code>]] and [[Poke4|<code>poke4()</code>]].
   
 
Note that using <code>dset()</code> and <code>dget()</code> partitions this memory into 64 standard PICO-8 numbers, but these are just helper functions and they are not mandatory. This memory region can be formatted in any desired manner. For instance, a bar chart with up to 51 bars could be encoded by saving a width for each bar and its color index, with the width being a full PICO-8 number and the color just being a byte:
 
Note that using <code>dset()</code> and <code>dget()</code> partitions this memory into 64 standard PICO-8 numbers, but these are just helper functions and they are not mandatory. This memory region can be formatted in any desired manner. For instance, a bar chart with up to 51 bars could be encoded by saving a width for each bar and its color index, with the width being a full PICO-8 number and the color just being a byte:
Line 122: Line 168:
 
This memory region represents the current [[DrawState|draw state]]. The values are as follows:
 
This memory region represents the current [[DrawState|draw state]]. The values are as follows:
   
  +
'''0x5f00-0x5f0f / 24320-24335'''
0x5f00-0x5f1f: Palette filtering ([[Pal|<code>pal()</code>]], [[Palt|<code>palt()</code>]]). 0x5f00-0x5f0f is palette #0 (the draw palette), and 0x5f10-0x5f1f is palette #1 (the screen palette). The index is the original color number, and bits 0-7 are the replacement color number. Bit 8 indicates whether the color should be treated as transparent (1=true).
 
  +
:Draw palette look-up table ([[Pal|<code>pal()</code>]], [[Palt|<code>palt()</code>]]). When PICO-8 is asked to draw a certain 4-bit color index, it looks up the color's index in this table to decide which ''actual'' 4-bit color index to write to screen memory. The 16 values in this table should have their lower 4 bits set to 0-15, to indicate which index is actually written to screen memory, while bit 5 should be either 0 for normal operation, or 1 (i.e. add 16 to the index) if the color index is to be transparent.
   
  +
'''0x5f10-0x5f1f / 24336-24351'''
0x5f20-0x5f23: Clipping region ([[Clip|<code>clip()</code>]]). The bounding box is described in four bytes, as coordinates from the top-left origin (0,0): 0x5f20=x1, 0x5f21=y1, 0x5f22=x2, 0x5f23=y2. Notice that this differs from the arguments to [[Clip|<code>clip()</code>]]: x2=x1+w, y2=y1+h.
 
  +
:Screen palette look-up table ([[Pal|<code>pal(...,1)</code>]]). PICO-8 reads this table while converting the color indices in screen memory into system ("hardware") colors to be shown on its display. As of this writing, there are ''officially'' only 16 system colors available, whose values range from 0 to 15. However, an additional, but undocumented, 16 colors appear to be available at values from 128 to 143, and [https://twitter.com/lexaloffle/status/1169094824474992640 zep appears to be fine with us knowing this].
   
  +
'''0x5f20-0x5f23 / 24352-24355'''
0x5f24: ''(unknown, please update this if you know)''
 
  +
:Clipping rectangle ([[Clip|<code>clip(x,y,w,h)</code>]]):
   
  +
:*0x5f20 / 24352: x_begin (no pixels < x_begin will be drawn)
0x5f25: Pen color ([[Color|<code>color()</code>]]). The bottom 4 bits are the current color index, from 0-15. The top 4 bits are typically 0 and unused, but when using fill patterns, they will be the secondary color index.
 
  +
:*0x5f21 / 24353: y_begin (no pixels < y_begin will be drawn)
  +
:*0x5f22 / 24354: x_end (no pixels >= x_end will be drawn)
  +
:*0x5f23 / 24355: y_end (no pixels >= x_end will be drawn)
   
  +
:These are somewhat different from the <code>clip(x,y,w,h)</code> arguments. Use <code>clip(xb,yb,xe-xb,ye-yb)</code> to set a clip rectangle using values like these.
0x5f26-0x5f27: Print cursor ([[Cursor|<code>cursor()</code>]]). 0x5f26=x, 0x5f27=y.
 
   
  +
:Note: Inside <code>clip()</code> the rectangle is clamped to the edges of the display before the GPU is configured. Expect x,y begin values to be in the range 0..127, and x,y end values to be in the slightly-larger range 0..128.
0x5f28-0x5f2b: Camera position ([[Camera|<code>camera()</code>]]). The x and y offsets are stored as 16-bit signed integers with the least significant byte first. 0x5f28-0x5f29=x offset, 0x5f2a-0x5f2b=y offset.
 
   
  +
'''0x5f24 / 24356'''
0x5f2c: Bit 2 (value 4) controls what this value does. If clear, bits 0 and 1 (values 1 and 2) control horizontal and vertical pixel-doubling. If bit 2 is set, they instead control screen mirroring, left-to-right and top-to-bottom, respectively. Thus, a value of 3 would produce a 64x64 screen, and a value of 7 would produce a 4-way kaleidoscope effect.
 
 
:''(unknown, please update this if you know)''
   
  +
'''0x5f25 / 24357'''
0x5f2d: If set to 1, devkit mode is enabled, allowing mouse coordinates and keyboard status to be checked via the [[Stat|<code>stat()</code>]] command.
 
 
:Pen color ([[Color|<code>color()</code>]]). The bottom 4 bits are the current color index, from 0-15. The top 4 bits are typically 0 and unused, but when using fill patterns, they will be the secondary color index.
   
  +
'''0x5f26-0x5f27 / 24358-24359'''
0x5f2e: (undocumented, but confirmed by zep) If set to 1, causes the current palette scheme (see [[Pal|<code>pal()</code>]] and/or the 0x5f00-0x5f1f memory range, above) to persist instead of being reset at the end of the program.
 
 
:Print cursor ([[Cursor|<code>cursor()</code>]]). 0x5f26=x, 0x5f27=y.
   
  +
'''0x5f28-0x5f2b / 24360-24363'''
0x5f30: (undocumented) If set to 1, suppresses the ''next'' attempt to bring up the pause menu. This can be done as late as discovering the pause button has been pressed this frame:
 
 
:Camera position ([[Camera|<code>camera()</code>]]). The x and y offsets are stored as 16-bit signed integers with the least significant byte first. 0x5f28-0x5f29=x offset, 0x5f2a-0x5f2b=y offset.
<syntaxhighlight lang="lua">
 
  +
  +
'''0x5f2c / 24364'''
  +
:This value sets the draw mode to normal, stretching, mirroring, flipping, or rotating.
  +
:* 0 = normal mode
  +
:* 1 = horizontal stretch, 64x128px screen, left half of normal screen
  +
:* 2 = vertical stretch, 128x64px screen, top half of normal screen
  +
:* 3 = both stretch, 64x64px screen, top left quarter of normal screen
  +
:* 5 = horizontal mirroring, left half copied and flipped to right half
  +
:* 6 = vertical mirroring, top half copied and flipped to bottom half
  +
:* 7 = both mirroring, top left quarter copied and flipped to other quarters
  +
:* 65-71 = same as 1-7?
  +
The following modes are introduces in 0.1.12d which is currently available on the BBS but not as a binary download yet.
  +
:* 129 = horizontal flip
  +
:* 130 = vertical flip
  +
:* 131 = both flip
  +
:* 133 = clockwise 90 degree rotation
  +
:* 134 = 180 degree rotation (effectively equivalent to 131)
  +
:* 135 = counterclockwise 90 degree rotation
  +
:* 193-199 = same as 129-235?
  +
  +
'''0x5f2d / 24365'''
 
:If set to 1, devkit mode is enabled, allowing mouse coordinates and keyboard status to be checked via the [[Stat#.7B30.E2.80.A636.7D_Mouse_and_keyboard_in_.22devkit_mode.22|<code>stat()</code>]] command.
  +
  +
'''0x5f2e / 24366'''
 
:(undocumented, but confirmed by zep) If set to 1, causes the current palette scheme (see [[Pal|<code>pal()</code>]] and/or the 0x5f00-0x5f1f memory range, above) to persist instead of being reset at the end of the program.
  +
  +
'''0x5f2f / 24367'''
  +
:(undocumented) If set to 1, pause the music and SFX playback engine, until 0 is written back to it. If set to 2, allow music to continue when the pause menu is displayed.
  +
  +
'''0x5f30 / 24368'''
 
:(undocumented) If set to 1, suppresses the ''next'' attempt to bring up the pause menu. This can be done as late as discovering the pause button has been pressed this frame:
 
::<syntaxhighlight lang="lua">
 
if(btn(6)) poke(0x5f30,1)
 
if(btn(6)) poke(0x5f30,1)
 
</syntaxhighlight>
 
</syntaxhighlight>
   
  +
'''0x5f31-0x5f33 / 24369-24371'''
0x5f31-0x5f33: Fill pattern ([[Fillp|<code>fillp()</code>]]). 0x5f31-0x5f32 contain the fill pattern as a 16-bit unsigned integer with the least significant byte first. 0x5f33's bit 0 is the related transparency bit.
+
:Fill pattern ([[Fillp|<code>fillp()</code>]]). 0x5f31-0x5f32 contain the fill pattern as a 16-bit unsigned integer with the least significant byte first. 0x5f33's bit 0 is the related transparency bit.
   
  +
'''0x5f34 / 24372'''
0x5f34: If set to 1, changes the PICO-8 drawing API to accept color values that incorporate not just one or two colors, but optionally include information about both the fill pattern and transparency right in the color value. From the manual:
+
:If set to 1, changes the PICO-8 drawing API to accept color values that incorporate not just one or two colors, but optionally include information about both the fill pattern and transparency right in the color value. From the manual:
<pre>
 
  +
<pre style="margin-left: 24px">
-- bit 0x1000.0000 means the non-colour bits should be observed
+
-- bit 0x1000.0000 means the non-colour bits should be observed
-- bit 0x0100.0000 transparency bit
+
-- bit 0x0100.0000 transparency bit
-- bits 0x00FF.0000 are the usual colour bits
 
-- bits 0x0000.FFFF are interpreted as the fill pattern
+
-- bits 0x00FF.0000 are the usual colour bits
  +
-- bits 0x0000.FFFF are interpreted as the fill pattern
 
</pre>
 
</pre>
   
  +
'''0x5f35-0x5f3b / 24373-24379'''
The remaining values up to 0x5f3f otherwise appear to be either undocumented or reserved for future use.
 
  +
:''(unknown, please update this if you know)''
  +
  +
'''0x5f3c-0x5f3f / 24380-24383'''
  +
:Ending position of the previous line drawn using <code>[[Line|line()]]</code>. If no line has been drawn, these values will be 0. The x and y coordinates are stored as 16-bit signed integers with the least significant byte first. 0x5f3c-0x5f3d=x coordinate, 0x5f3e-0x5f3d=y coordinate. (Note: This was added in PICO-8 0.1.12b.)
   
 
== Hardware state ==
 
== Hardware state ==
Line 161: Line 254:
 
These memory addresses represent or control various aspects of the hardware. These are undocumented.
 
These memory addresses represent or control various aspects of the hardware. These are undocumented.
   
  +
0x5f40-0x5f43 are control registers for the audio hardware. They're encoded with the following format:
0x5f40: Bitmask to half each audio channel's clock rate. Bit 0 (value 1) is for Channel 1, Bit 1 (value 2) is for Channel 2, and so on. The upper four bits are not used.
 
   
  +
xxxx-ch3-ch2-ch1-ch0
0x5f41: Bitmask to enable reverb for each channel. The bits have the same effect as 0x5f40.
 
   
  +
Setting bit 0 (ch0, value 1) enables the effect for channel 0, bit 1 (ch1, value 2) is for channel 1, etc. The "x" bits are unused. The features that each register control are as follows:
0x5f42: Bitmask to distort the waveforms of each channel.
 
   
  +
'''0x5f40 / 24384'''
0x5f43: Bitmask to enable a lowpass filter for each channel.
 
  +
:Halves an audio channel's clock rate. The main rate is 22.05 KHz, and enabling the feature for a channel will cause it to be 11.025 KHz instead. This causes SFX and arp speeds to be halved, and the note pitch to be an octave lower.
   
  +
'''0x5f41 / 24385'''
The remaining values up to 0x5f7f are undocumented.
 
  +
:Enables reverb (echo) for a channel.
  +
  +
'''0x5f42 / 24386'''
  +
:Distorts the output of a channel. The audio becomes 3-bit (8 linear levels) without any dithering.
  +
  +
'''0x5f43 / 24387'''
 
:Enables a lowpass filter for a channel.
  +
  +
:The priorities of the features are as follows, from left (lowest priority) to right (highest priority):
  +
  +
:Reverb < Distortion < Lowpass < Half-Clock
  +
  +
'''0x5f44-0x5f7f / 24388-24447'''
 
:The remaining registers up to 0x5f7f are undocumented.
   
 
== GPIO pins ==
 
== GPIO pins ==
   
This experimental feature provides programs access to the [[GPIO]] (general purpose input/output) hardware pins of a Raspberry Pi or CHIP device. These addresses can be used to accept digital input from or write digital output to devices connected to the pins.
+
This experimental feature provides programs access to the [[GPIO]] (general purpose input/output) hardware pins of a Raspberry Pi or CHIP device. These addresses can be used to accept digital input from or write digital output to devices connected to the pins. JavaScript code that runs in a browser can also access them by defining a global array named ''pico8_gpio''. There are up to 128 pins, depending on the platform.
  +
  +
'''0x5f80-0x5fff / 24448-24575'''
  +
:Each byte represents the value of 1 pin. The possible values vary depending on the platform.
   
 
== Screen data ==
 
== Screen data ==
Line 179: Line 290:
 
This 8,192-byte (8 kilobyte) region contains the graphics buffer. This is what is modified by the built-in drawing functions, and is what is copied to the actual display at the end of the [[GameLoop|game loop]] or by a call to [[Flip|<code>flip()</code>]].
 
This 8,192-byte (8 kilobyte) region contains the graphics buffer. This is what is modified by the built-in drawing functions, and is what is copied to the actual display at the end of the [[GameLoop|game loop]] or by a call to [[Flip|<code>flip()</code>]].
   
  +
'''0x6000-0x7fff / 24576-32767'''
See the description of the sprite sheet, above, for information on how this image is represented in memory.
 
  +
:All 128 rows of the screen, top to bottom. Each row contains 128 pixels in 64 bytes. Each byte contains two adjacent pixels, with the lo 4 bits being the left/even pixel and the hi 4 bits being the right/odd pixel.
  +
  +
== Lua Memory ==
  +
The Memory used by Lua (global variables, local variables, tables, etc.) is entirely separate from the Pico-8 memory discussed above and is limited to 2 [[MiB]].
  +
  +
The amount of memory currently used by the program can be checked with [[Stat|stat(0)]] and adds up as follows (all numbers are in bytes):
  +
* '''nil / boolean / number''' - no extra cost.
  +
* '''string''' - 17 + 1 * (# of characters)
  +
  +
Strings of length <= 40 are always interned, meaning creating such a string again (through any means) will simply use the previously created string and cost nothing.
  +
  +
On the other hand, interned strings are also stored in a global hash table, which grows whenever the number of interned strings reaches a new power of 2. Here, each interned string costs an additional ~4-8 bytes, though this cost is only observable - in bulk - whenever the hash table grows.
  +
* '''table''' - 32 + 8 * nextpow2(# of 'array' entries) + 20 * nextpow2(# of 'hash' entries)
  +
  +
Here, nextpow2 gives the next power of 2 (e.g. 2 -> 2, 3 -> 4, 4 -> 4, 5 -> 8, 130 -> 256).
  +
  +
For example, {1,2,a=3,b=4,c=5} takes 128 bytes: 32 + 8 * 2 + 20 * 4
  +
* '''function '''- 16 + 4 * (# of captured variables) + 32 * (# of newly captured variables)
  +
  +
A captured variable is any local variable declared outside the function, that's accessed inside the function.
  +
  +
A "newly" captured variable is merely one that wasn't captured before by other functions.
  +
  +
A function that uses any globals automatically captures _ENV, and this counts as a captured variable. (Unless _ENV is explicitly re-declared, it never counts as a newly captured variable, though.)
  +
  +
If a function is created multiple times, the previously created instance is reused if possible, thus costing nothing. The previous instance can be reused if it has no captured variables, or if it has captured variables but they're all the same variables as the captured variables of the new function.
  +
* '''thread''' (created by cocreate) - 352 bytes.
 
[[Category:Reference]]
 
[[Category:Reference]]

Revision as of 10:18, 26 February 2020

PICO-8 has 32 kilobytes of addressable memory, used for graphics, map, sound, music, and direct access to hardware features such as persistent cartridge data and GPIO pins. Programs can read from and write to this data using peek() and poke().

While many games can use the built-in functions for graphics and sound, memory access enables advanced techniques such as repurposing memory regions or generating graphics and sound data algorithmically. For features such as the GPIO pins, peek() and poke() are currently the only way to access the feature.

The first 16 kilobytes are copied from the cartridge into memory when the cartridge is loaded. When the cartridge changes a value in memory, it is only changed in memory and not in the cartridge itself.

The cstore() function can be used to write memory data to the cartridge file. The reload() function can also be used to load cartridge data back into memory, or load a region of memory from another cartridge file.

The Lua program stack (variables, etc.) is not stored in addressable memory and cannot be accessed directly by the program.

See also P8FileFormat, P8PNGFileFormat.

Memory map

This is the high-level memory map for addressable memory:

Start End Purpose
0x0 0x0fff Sprite sheet (0-127)
0x1000 0x1fff Sprite sheet (128-255) / Map (rows 32-63) (shared)
0x2000 0x2fff Map (rows 0-31)
0x3000 0x30ff Sprite flags
0x3100 0x31ff Music
0x3200 0x42ff Sound effects
0x4300 0x5dff General use (or work RAM)
0x5e00 0x5eff Persistent cart data (64 numbers = 256 bytes)
0x5f00 0x5f3f Draw state
0x5f40 0x5f7f Hardware state
0x5f80 0x5fff GPIO pins (128 bytes)
0x6000 0x7fff Screen data (8k)

The in-memory data formats for each section are described below.

Sprite sheet

The sprite sheet is represented in memory as one large image, 128 x 128 pixels. Each sprite tile is an 8 x 8 region in this image. Each sprite tile gets an ID, counting from 0, left to right, top to bottom.

Each pixel can be one of 16 colors, and is represented by 4 bits. An 8-bit byte represents two pixels, horizontally adjacent, where the most significant (leftmost) 4 bits is the right pixel of the pair, and the least significant 4 bits is the left pixel. Pixels are stored from left to right, top to bottom.

Other than this swapping within the byte, pixels are arranged in memory going left to right, top to bottom, for the entire 128 x 128 pixel image (using 128 * 64 = 8,192 bytes).

The bottom half of the sprite sheet and the bottom half of the map region overlap in memory. Typically, a game uses this region for only one purpose or the other.

0x0000-0x0fff / 0-4095

The upper 64 rows in the sprite sheet. Each 64-byte row contains 128 pixels. Each byte contains two adjacent pixels, with the lo 4 bits being the left/even pixel and the hi 4 bits being the right/odd pixel.

0x1000-0x1fff / 4096-8191

The lower 64 rows in the sprite sheet. Same format as above. Overlaps lower half of Map (see below).

Map

The map is 128 tiles wide by 64 tiles high. Each tile is one of the 256 tiles from the sprite sheet, one byte per tile (using 128 * 64 = 8,192 bytes). The value is the sprite ID.

The map is read from left to right, top to bottom order.

0x1000-0x1fff / 4096-8191

The lower 32 rows of the map. Each row contains 128 tiles. Each byte contains one tile index. Overlaps lower half of Sprite Sheet (see above).

0x2000-0x2fff / 8192-12287

The upper 32 rows of the map. Each row contains 128 tiles. Each byte contains one tile index.

Sprite flags

Each sprite tile has 8 flags, each of which can be on or off. One byte stores the flags for a sprite tile. Bytes are arranged by sprite ID, for a total of 256 bytes.

In the graphics editor, the flags are arranged left to right from LSB to MSB: red=1, orange=2, yellow=4, green=8, blue=16, purple=32, pink=64, peach=128.

0x3000-0x30ff / 12288-12543

Each byte represents the flags for the associated sprite.

Music

There are 64 music patterns. Each music pattern uses four bytes to assign a sound effect or silence to each of four channels. (4 * 64 = 256 bytes.)

If a sound effect is assigned to a channel, bit 6 is 0, and bits 5-0 are the sound ID (0 through 63). If the channel is silent, bit 6 is 1, and bits 5-0 are not used.

Bit 7 is used to describe the flags for the music pattern. Bit 7 of the first byte (channel 1) is "begin pattern loop." Bit 7 of the second byte (channel 2) is "end pattern loop." Bit 7 of the third byte (channel 3) is "stop at end of pattern." (Bit 7 of the fourth byte is unused.)

Sound effects

There are 64 sound effects. Each sound effect is 68 bytes, with two bytes for each of 32 notes and then one byte for the editor mode, one byte for the speed, two bytes for the loop range (start, end). (64 * 68 = 4,352 bytes.)

The effect speed is a value between 0 and 255, representing the duration of each note in the effect, as a multiple of 1/128 seconds. Using the full effect length of 32 notes, with a speed of 1, the full effect plays in 1/4 second. With a speed of 4, the full effect plays in 1 second.

In an effect used for a music pattern, beats per minute can be calculated based on how many notes per "beat." For example, if an effect plays a "beat" every four notes in an effect, a speed of 15 is equivalent to 15/128 seconds per note, 15*4/128 seconds per four notes (one beat), (15*4)/(128*60) minutes per beat, or (128*60)/(15*4) = 128 beats per minute.

Each note is encoded in 16 bits, in Little Endian style, with the low 8 bits in the first byte, and the hi 8 bits in the second, formatted like so:

Second byte / Hi 8 bits
c e e e v v v w
First byte / Lo 8 bits
w w p p p p p p
  • c: when c is 1, waveform is a custom instrument corresponding to sfx 0-7; otherwise it is one of the eight built-in waveforms (PICO-8 0.1.11+)
  • eee: effect (0-7)
  • vvv: volume (0-7)
  • www: waveform (0-7)
  • pppppp: pitch (0-63)

For example, a note's pitch and effect can be seen using peek(0x3200 + 68*track + 2*time), and instrument and volume by peek(0x3200 + 68*track + 2*time + 1). So if 30 was seen for instrument and volume, they are stored in bits 0b0011110 so the instrument is 0b001 (1) and volume is 0b111 (7); the last bit is used for sfx instrument flag, 0 if off, 1 if on.

General use

0x4300-0x5dff / 17152-24063 This memory region is available for the program to use for any purpose.

This region is not loaded from the cartridge, though the reload() function can be used to copy data into this region from a cartridge file.

(Undocumented?) This region is not reset when loading another cart via load(), so can be used for passing data to and from the loaded cart.

Persistent cart data

0x5e00-0x5eff / 24064-24319 After persistent data is initialized with the cartdata() function, the 256-byte region from 0x5e00 to 0x5eff represents the 64 number values accessible by dset() and dget(). These numbers are stored in the same 4-byte, little endian, 16.16 fixed-point format used by peek4() and poke4().

Note that using dset() and dget() partitions this memory into 64 standard PICO-8 numbers, but these are just helper functions and they are not mandatory. This memory region can be formatted in any desired manner. For instance, a bar chart with up to 51 bars could be encoded by saving a width for each bar and its color index, with the width being a full PICO-8 number and the color just being a byte:

function bar_set(index, width, color)
  local addr = 0x5e00 + index*5
  poke4(addr, width)
  poke(addr+4, color)
end

function bar_get(index)
  local addr = 0x5e00 + index*5
  return peek4(addr), peek(addr+4)
end

Draw state

This memory region represents the current draw state. The values are as follows:

0x5f00-0x5f0f / 24320-24335

Draw palette look-up table (pal(), palt()). When PICO-8 is asked to draw a certain 4-bit color index, it looks up the color's index in this table to decide which actual 4-bit color index to write to screen memory. The 16 values in this table should have their lower 4 bits set to 0-15, to indicate which index is actually written to screen memory, while bit 5 should be either 0 for normal operation, or 1 (i.e. add 16 to the index) if the color index is to be transparent.

0x5f10-0x5f1f / 24336-24351

Screen palette look-up table (pal(...,1)). PICO-8 reads this table while converting the color indices in screen memory into system ("hardware") colors to be shown on its display. As of this writing, there are officially only 16 system colors available, whose values range from 0 to 15. However, an additional, but undocumented, 16 colors appear to be available at values from 128 to 143, and zep appears to be fine with us knowing this.

0x5f20-0x5f23 / 24352-24355

Clipping rectangle (clip(x,y,w,h)):
  • 0x5f20 / 24352: x_begin (no pixels < x_begin will be drawn)
  • 0x5f21 / 24353: y_begin (no pixels < y_begin will be drawn)
  • 0x5f22 / 24354: x_end (no pixels >= x_end will be drawn)
  • 0x5f23 / 24355: y_end (no pixels >= x_end will be drawn)
These are somewhat different from the clip(x,y,w,h) arguments. Use clip(xb,yb,xe-xb,ye-yb) to set a clip rectangle using values like these.
Note: Inside clip() the rectangle is clamped to the edges of the display before the GPU is configured. Expect x,y begin values to be in the range 0..127, and x,y end values to be in the slightly-larger range 0..128.

0x5f24 / 24356

(unknown, please update this if you know)

0x5f25 / 24357

Pen color (color()). The bottom 4 bits are the current color index, from 0-15. The top 4 bits are typically 0 and unused, but when using fill patterns, they will be the secondary color index.

0x5f26-0x5f27 / 24358-24359

Print cursor (cursor()). 0x5f26=x, 0x5f27=y.

0x5f28-0x5f2b / 24360-24363

Camera position (camera()). The x and y offsets are stored as 16-bit signed integers with the least significant byte first. 0x5f28-0x5f29=x offset, 0x5f2a-0x5f2b=y offset.

0x5f2c / 24364

This value sets the draw mode to normal, stretching, mirroring, flipping, or rotating.
  • 0 = normal mode
  • 1 = horizontal stretch, 64x128px screen, left half of normal screen
  • 2 = vertical stretch, 128x64px screen, top half of normal screen
  • 3 = both stretch, 64x64px screen, top left quarter of normal screen
  • 5 = horizontal mirroring, left half copied and flipped to right half
  • 6 = vertical mirroring, top half copied and flipped to bottom half
  • 7 = both mirroring, top left quarter copied and flipped to other quarters
  • 65-71 = same as 1-7?

The following modes are introduces in 0.1.12d which is currently available on the BBS but not as a binary download yet.

  • 129 = horizontal flip
  • 130 = vertical flip
  • 131 = both flip
  • 133 = clockwise 90 degree rotation
  • 134 = 180 degree rotation (effectively equivalent to 131)
  • 135 = counterclockwise 90 degree rotation
  • 193-199 = same as 129-235?

0x5f2d / 24365

If set to 1, devkit mode is enabled, allowing mouse coordinates and keyboard status to be checked via the stat() command.

0x5f2e / 24366

(undocumented, but confirmed by zep) If set to 1, causes the current palette scheme (see pal() and/or the 0x5f00-0x5f1f memory range, above) to persist instead of being reset at the end of the program.

0x5f2f / 24367

(undocumented) If set to 1, pause the music and SFX playback engine, until 0 is written back to it. If set to 2, allow music to continue when the pause menu is displayed.

0x5f30 / 24368

(undocumented) If set to 1, suppresses the next attempt to bring up the pause menu. This can be done as late as discovering the pause button has been pressed this frame:
  if(btn(6)) poke(0x5f30,1)

0x5f31-0x5f33 / 24369-24371

Fill pattern (fillp()). 0x5f31-0x5f32 contain the fill pattern as a 16-bit unsigned integer with the least significant byte first. 0x5f33's bit 0 is the related transparency bit.

0x5f34 / 24372

If set to 1, changes the PICO-8 drawing API to accept color values that incorporate not just one or two colors, but optionally include information about both the fill pattern and transparency right in the color value. From the manual:
-- bit  0x1000.0000 means the non-colour bits should be observed
-- bit  0x0100.0000 transparency bit
-- bits 0x00FF.0000 are the usual colour bits
-- bits 0x0000.FFFF are interpreted as the fill pattern

0x5f35-0x5f3b / 24373-24379

(unknown, please update this if you know)

0x5f3c-0x5f3f / 24380-24383

Ending position of the previous line drawn using line(). If no line has been drawn, these values will be 0. The x and y coordinates are stored as 16-bit signed integers with the least significant byte first. 0x5f3c-0x5f3d=x coordinate, 0x5f3e-0x5f3d=y coordinate. (Note: This was added in PICO-8 0.1.12b.)

Hardware state

These memory addresses represent or control various aspects of the hardware. These are undocumented.

0x5f40-0x5f43 are control registers for the audio hardware. They're encoded with the following format:

xxxx-ch3-ch2-ch1-ch0

Setting bit 0 (ch0, value 1) enables the effect for channel 0, bit 1 (ch1, value 2) is for channel 1, etc. The "x" bits are unused. The features that each register control are as follows:

0x5f40 / 24384

Halves an audio channel's clock rate. The main rate is 22.05 KHz, and enabling the feature for a channel will cause it to be 11.025 KHz instead. This causes SFX and arp speeds to be halved, and the note pitch to be an octave lower.

0x5f41 / 24385

Enables reverb (echo) for a channel.

0x5f42 / 24386

Distorts the output of a channel. The audio becomes 3-bit (8 linear levels) without any dithering.

0x5f43 / 24387

Enables a lowpass filter for a channel.
The priorities of the features are as follows, from left (lowest priority) to right (highest priority):
Reverb < Distortion < Lowpass < Half-Clock

0x5f44-0x5f7f / 24388-24447

The remaining registers up to 0x5f7f are undocumented.

GPIO pins

This experimental feature provides programs access to the GPIO (general purpose input/output) hardware pins of a Raspberry Pi or CHIP device. These addresses can be used to accept digital input from or write digital output to devices connected to the pins. JavaScript code that runs in a browser can also access them by defining a global array named pico8_gpio. There are up to 128 pins, depending on the platform.

0x5f80-0x5fff / 24448-24575

Each byte represents the value of 1 pin. The possible values vary depending on the platform.

Screen data

This 8,192-byte (8 kilobyte) region contains the graphics buffer. This is what is modified by the built-in drawing functions, and is what is copied to the actual display at the end of the game loop or by a call to flip().

0x6000-0x7fff / 24576-32767

All 128 rows of the screen, top to bottom. Each row contains 128 pixels in 64 bytes. Each byte contains two adjacent pixels, with the lo 4 bits being the left/even pixel and the hi 4 bits being the right/odd pixel.

Lua Memory

The Memory used by Lua (global variables, local variables, tables, etc.) is entirely separate from the Pico-8 memory discussed above and is limited to 2 MiB.

The amount of memory currently used by the program can be checked with stat(0) and adds up as follows (all numbers are in bytes):

  • nil / boolean / number - no extra cost.
  • string - 17 + 1 * (# of characters)

Strings of length <= 40 are always interned, meaning creating such a string again (through any means) will simply use the previously created string and cost nothing.

On the other hand, interned strings are also stored in a global hash table, which grows whenever the number of interned strings reaches a new power of 2. Here, each interned string costs an additional ~4-8 bytes, though this cost is only observable - in bulk - whenever the hash table grows.

  • table - 32 + 8 * nextpow2(# of 'array' entries) + 20 * nextpow2(# of 'hash' entries)

Here, nextpow2 gives the next power of 2 (e.g. 2 -> 2, 3 -> 4, 4 -> 4, 5 -> 8, 130 -> 256).

For example, {1,2,a=3,b=4,c=5} takes 128 bytes: 32 + 8 * 2 + 20 * 4

  • function - 16 + 4 * (# of captured variables) + 32 * (# of newly captured variables)

A captured variable is any local variable declared outside the function, that's accessed inside the function.

A "newly" captured variable is merely one that wasn't captured before by other functions.

A function that uses any globals automatically captures _ENV, and this counts as a captured variable. (Unless _ENV is explicitly re-declared, it never counts as a newly captured variable, though.)

If a function is created multiple times, the previously created instance is reused if possible, thus costing nothing. The previous instance can be reused if it has no captured variables, or if it has captured variables but they're all the same variables as the captured variables of the new function.

  • thread (created by cocreate) - 352 bytes.