Log In  

I noticed that load() supports filenames without extensions and will pick filebasename.p8 if it exists, else filebasename.p8.png (I didn't exactly try the priority order, as there is only either a .p8 or .p8.png in my distributed game folder).

However, reload() won't work with a file basename. It needs the .p8 or .p8.png extension. When distributing a game both for p8 and png though, you don't know in advance what you'll need, and would need to create two versions of the code, one reloading files in .p8, the other reloading files in .p8.png, for both versions to work. I actually wrote a string replacement script to support them both!

It would be nice if reload() supported file basename like load() for this reason. I don't know if this is a bug report or a suggestion, but I would expect reload() to be consistent with load() so I opened this thread in the bug section nevertheless.

P#96060 2021-08-15 18:29

Hey, I've just triggered with profiling overlay you see in the top-right of the attached screenshot, and I cannot find how I enabled it. It would be nice to use since I was using my own custom profiler (printing stats) so far but this one has a nice graph and shows clearly when I drop to 30 FPS.

It really is an overlay, not part of the game. As a matter of fact, taking a screen capture with F1 with ignore the overlay!

As a hint, I was reload my game with a script that sends keystrokes Ctrl+R to the PICO-8 window. Maybe I pressed something else, or the keystrokes were not correctly registered at that time, and it triggered another shortcut; which I cannot find at all in the documentation!

Note: this happened in the editor, not the runtime binary version of PICO-8.

P#95654 2021-08-04 18:26 ( Edited 2021-08-04 18:27)

Calling this in editor:


will crash the editor instantly.

Opening pico8 in terminal, or running a script in headless mode containing this line (pico8 -x script.p8), allows us to see:

Segmentation fault (core dumped)

Interestingly, mkdir() (no argument at all) just shows the help, like mkdir without brackets at all.

P#86297 2021-01-09 17:58 ( Edited 2021-01-21 18:23)

I noticed that the screenshot captures done with F1 from the editor contain a black color #020408, while a system screenshot will show that PICO-8 uses #000000 while running.

This caused some issues as I was editing screen captures, Aseprite noticed that the color didn't match the black color from the PICO-8 palette, and operations like color replacement failed.

This may have been the case from the start, and I have no idea how many times I used screenshots in my editing process, possibly mixing "good" and "bad" black together. As they are not distinguishable with bare eyes this may be a problem for later (e.g. I try to fill an area with color bucket but it only colors a small area).

I could only find one occurrence of this color, on the PICO-8 Wikipedia talk: https://en.wikipedia.org/wiki/Talk:Pico-8

Apparently the old page was mentioning #020408 for black. Either it was the old color, or the author checked the colors from an F1 screenshot (and I would have done the same!).

I don't know if other colors are different during screenshot.
I don't know if it's intentional for web export, human eye convenience or anything, or if it's just an old value that was not updated.

P#86291 2021-01-09 15:20

Sometimes your cartridge fits in the token count, but not the characters count / compressed size, so you can't export it until you reduce the number of characters in the cartridge. You'd also like to keep comments, meaningful variable names and even debug code where you can, in case you're gonna continue working on the code.

One way to do this is to use a build pipeline:

  • copy your source file(s) to an intermediate directory
  • process file(s) to reduce code size
  • output final cartridge

If you use picotool or work with compiled languages, you should be familiar with that process. It may sound a bit overkill for PICO-8, but is very useful if you're stuck in the case mentioned above.

This is what I do when working with my custom framework pico-boots, but while I don't think many devs would be interested in using a complete framework for PICO-8 written by somebody else, they may be interested in the individual processing steps described below. You can always refer to pico-boots' repository for implementation details.

Note that I use picotool to build my cartridge from multiple sources, but the techniques I use apply to single files too. For those also using picotool, I'll explain for which Step the processing should be applied: on individual sources (pre-processing) or on the output cartridge (post-processing).


  • Comment stripping
  • Minification
  • Debug code stripping
    • Multi-line
    • Single-line
  • Going further

Comment stripping

Probably the most obvious, you'll want to remove single line ("--") and block ("--[[ ]]") comments.

I used to do it manually; now the minification step does it for me, so I won't dwell on it. However, if you already use very short variable names but have lots of comments, it's worth trying comment stripping alone.

Single line comment stripping is easy to implement in a file processing script, block comment may be a bit trickier.

Step: pre-processing or post-processing


Code minification mainly consists in variable/key name shortening, space trimming and comment stripping. You can whatever does the job. However, note that minifiers are written for pure Lua and may not like PICO-8 shortcuts such as single-line

if(cond) effect


a += 5

So you may want to expand those into pure Lua statements, manually or inside your pipeline (don't worry though, minification will often more than make up for the loss of space).

If you use picotool, note that it generates a single-line "if(cond) effect" during the build. So you'll need to expand that in your pipeline post-processing, just before minification.

Personally, I use a custom branch in my fork of luamin. It's basically Luamin plus a few features/fixes:

  • option "--minify-level" for aggressive member minification: useful if you want to minify even attribute and method names (requires extra care!)
  • option "--newline-separator" for partial newline preservation for easier debugging: otherwise the code is a veeery long line and error messages just tell you "assert on line 1" (note that there is only a newline where luamin would put a ';' without the option, so clauses ending with brackets, like function definitions, will still chain into longer lines)
  • works outside the terminal (e.g. in Sublime Text)
    (more info on minification and npm in pico-boots README)

I know that picotool has a --lua-minify option, but it was too aggressive for me (it minifies even "__call" which breaks metatable logic).

Step: pre-processing or post-processing (but if using aggressive minification, post-processing only so member names are minified the same way across the cartridge)


function demo_app.instantiate_gamestates() -- override
  return {main_menu(), debug_demo(), input_demo(), render_demo()}

function demo_app.on_pre_start() -- override

function demo_app.on_post_start() -- override
  -- enable mouse devkit

function demo_app.on_reset() -- override


function n.o()return{i(),j(),k(),l()}end
function n.p()end
function n.q()g:r(true)h:s(m.t.u)end
function n.v()h:s(nil)end

Implementation example

There is not much to do since it's already in the Luamin package, which you can get using "npm install/update" (see package.json).

However, if you're working on an actual .p8 cartridge rather than pure Lua code, you may want to extract the lua section, minify it and reinject it back. minify.py does precisely that (and also expands single-line "if(cond) effect").

Possible improvement on luamin for PICO-8

Only use lower characters to generate minified identifiers (see IDENTIFIER_PARTS in luamin.js). Otherwise, since PICO-8 auto-lowers characters when opening code in the integrated editor, it may cause variable conflicts ("Ab" becomes "ab" which may be another variable in scope) or even prevent cartridge from running ("Do" becomes "do" which is a keyword).

Debug code stripping


You can use whatever you want to flag debug code and remove it for the release build. However, you need some way to tell your pipeline that you are making a debug vs a release build.

On my projects, I use generic symbol-based preprocessing similar to the one in C# (or C++), but very much simplified. You define a set of symbols for your current build config (e.g. debug config defines ["assert", "log"], release config defines nothing). Then you surround parts you don't want in some build configs with special markers:

-- will be stripped in release
#if log
printh("Player hit!")
printh("Remaining HP: "..player.hp)

During build, any code surrounded by undefined symbols is stripped.

Of course, if you don't need one symbol per debug feature like me, you can just define "debug" for the debug config and surround all your debug code with "#if debug" and "#endif".

Step: pre-processing or post-processing, but recommend pre-processing to make core build faster, as there would be less code to assemble


#if assert
assert(damage > 0)

player.hp = player.hp - damage

#if log
printh("Player hit!")
printh("Remaining HP: "..player.hp)

becomes in release config:

player.hp = player.hp - damage


For single-line, you can write a simple parser that strips line calling certain functions.

For instance, I strip all single-line "assert(...)" calls if the "assert" symbol is not defined. It means that in the example above, I don't even need the "#if assert" anymore. It's very convenient when you have many logs and assertions. But multi-line stripping is still useful for more complex behaviors.

Step: same as multi-line


assert(damage > 0)

player.hp = player.hp - damage

log("Player hit!")
log("Remaining HP: "..player.hp)

becomes in release config:

player.hp = player.hp - damage

Implementation example

See both multi-line and single-line stripping in preprocess.py

It also contains a reversed stripping tag "--[[#pico8" and "--#pico8]]" that comments out the code until it is built into a cartridge; but that's only useful if you run unit tests in pure Lua.

Going further

If your game has a lot of text, string compression is your next step. You can make your own, or check out a tool like p8advent (also see post which mentions alternative).

Also, if you're interested in the full build pipeline I use, check out the generic build script and the demo project script using the former.

P#72970 2020-02-10 20:48 ( Edited 2020-02-10 21:01)

When printing with no coordinate arguments, text is printed on the next line after the last prompt position. In addition, when the bottom of the screen is reached, all previous graphics are moved upward.

It is also possible to print multiple lines at once, and when printed at the bottom, it will also move all previous graphics from multiple lines.

However, the lines after the 1st one won't be printed correctly. The 2nd line's bottom half will be hidden, and the lines after that will be invisible.


  1. Start PICO-8
  2. Enter print("1\n2\n3")
  3. Repeat until prompt reaches the bottom of the screen
  4. Repeat. From then on, "2" will be cut and "3" will be invisible.


This also applies to Lua multiline strings using [[ ]], [==[ ]==], etc. instead of "\n".

P#60412 2018-12-28 14:47

Follow Lexaloffle:        
Generated 2022-01-28 16:53:24 | 0.077s | Q:14