Log In  

PICO-8 0.2.3 is now up on lexaloffle, Humble, itch.io, and for PocketCHIP.

This update is focused on resolving runtime issues, with a couple of small but handy features thrown in for good measure:

Lucky Draw

To grab 32 random cartridges from the BBS, there is now a 'Lucky Draw' list in SPLORE. It is more likely to select cartridges that have more stars, but even unrated carts have a decent chance of appearing. Perhaps this will be a way to unearth some undiscovered gems, or just to find something new to play without scrolling back through several years of carts.

The list is cached, so it only changes every 2 minutes or so. But you can keep paging through the list to get new items forever.

Live Token / Character Count

Select some text in the code editor to view how many characters or tokens are contained within.

Shorthand Print Statements

The shorthand version of print (?"hello") used to require no preceding statement be on the same line, but you can now mix it with things like the shorthand IF statement, as long as it is the last thing on the line:

IF (PGET(X,Y)>0) HIT=1 ?"\ADAF"

Thanks to @Liquidream for suggesting this. It should be handy for things like tweetcarts and PICO-1K Jam (which coincidentally is also organized by Liquidream!)

New Manual

The PICO-8 Manual is still a work in progress, but it went through a large update last month, with new formatting, dark mode, linkable headers, and more printer-friendly. You can find it on the resources page:


The changelog has been separated into a text file here:


The pico-8.txt included in the distributables has changed to a short version that links to the online manual, but later on I'll bring back the full ascii version and keep it in sync with the html version.

.P8.ROM Format

This isn't a very useful feature unless you are manipulating PICO-8 cartridges with external tools, but it has always irked me that it is not possible to write 32k of PICO-8 cartridge to a file that is 32k!



Large Numbers

tostr() and tonum() now take format flags that make it easier to deal with large numbers.


PICO-8's numbers are all 16:16 fixed point, which basically means that every number is internally stored as a large 32-bit integer that is divided by 65536 to get the value in Lua. So for example, if you want to use that large integer for something like scores that need to go above the usual maximum of 32767, bit 0x2 can be used to display it in the raw integer form:

?TOSTR(3, 0x2)
?TONUM("196608", 0x2)

To add 10 points to a score stored in this way, you'd need to shift it right 16 bits:

SCORE += 10>>16

CPU Counting

0.2.3 contains two changed to cpu costs which does not effect many cartridges:

  1. In 0.2.2c, it was cheaper to write "local a=0+b" than "local a=b" and also "local a=0-b" than "local a=-b". This is because the Lua vm instruction for addition was cheaper than local assignment (OP_MOVE), and for unary minus (OP_UNM). The best solution I could find was simply to reduce the cost of those two instructions to 1 cycle instead of 2, resulting in a slight speed increase in some cases.

  2. peeking or poking multiple values in 0.2.2c did not cost any additional cpu, so doing something like: poke4(0,peek4(0x1000,0x1000)) was completely free! The same line in 0.2.3 now costs the same as doing an equivalent memcpy.

Future Plans

Next up for PICO-8 is a 64-bit Raspberry Pi Build, and also a preview of a web version that is also handy for running PICO-8 on Chromebooks. I'm also still working on online scores, which required developing some bespoke infrastructure that is optimised for PICO-8's usage patterns, and can handle traffic from exported carts without needing to start charging for PICONET subscriptions or anything like that. I'll test it next month with the release of https://www.doodlemud.com, which is a multiplayer drawing game designed to battletest PICO-8's backend before exposing it to precious cartridge data!



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

P#96897 2021-09-06 21:26


Next up for PICO-8 is a 64-bit Raspberry Pi Build

Oh my oh my, I am very much excited for this!

P#96972 2021-09-06 21:38
:: Numzyx

very glad that the 0x808 audio lowpass filter can be optionally turned off, i actually like the crunch of the high frequency artifacts

P#96976 2021-09-06 22:43

Thanks for another great update @zep! 🤓
Many thanks especially for the quality-of-life improvements for #Pico1k jam and #Tweetcart's, etc. 🙏

P#96987 2021-09-07 04:13

A Webversion !!! YESS!!! This way i can use Pico8 soon on my Samsung Tablet TabS6 and Keyboard on the go!

P#96988 2021-09-07 05:15

@StinkerB06 thanks (as if all my games did not use reload... :facepalm: )

.rom question - is the goal to have 32k data carts or only as a convenient way to generate carts (without the $ù@@## sfx/music format?)

correction: reload does work with p8.rom files
feature request: ability to reload the full 32k of a p8.rom files (now possible with 0x8000 region)
(should multicart games be limited by size rather than number of files?)

P#96990 2021-09-07 11:20 ( Edited 2021-09-09 05:58)
:: zep

@freds72 .p8.rom is only supported by LOAD/SAVE.

I was imagining only using it for authoring single carts, but yes -- I suppose it should really be treated the same by CSTORE/RELOAD. I'll wishlist that for the next update. I'd like to keep the code vs. data section rules the same though (as oddball as they are), so it won't be a way to get the full 32k as readable data.

P#96992 2021-09-07 12:18


I have a problem with some code that worked up to the previous version:

  if stat(30)  then
      local k = ord(stat(31))

ord(stat(31)) always returns null but was returning the correct value before.

It works if changed to:

  if stat(30)  then
      local k = stat(31) k=ord(k)
P#97001 2021-09-07 14:03
:: touk

Hi @zep, thanks for the update!

Could you perhaps support .p8.rom via commandline "-export" like .p8.png?

I'm new to PICO-8 and I find SAVE vs EXPORT slightly confusing, eg. you use SAVE to write a .p8.png cartridge, but -export to do the same via commandline.

Just a suggestion! Useful for scripting and external tools.

P#97012 2021-09-07 17:08

So excited for the web version!! Thank you zep!

P#97019 2021-09-07 20:26
:: icedog

A New Version!!!Tanks @zep

P#97050 2021-09-08 11:37

@freds72 It looks like you messed up the order of the arguments to reload().

P#97079 2021-09-08 21:59
:: merwok

Touk> it used to be clearer: we used 'save' (in the console) for the cart itself (P8 or P8PNG format), and 'export' for bits like the spritesheet or a music track.
HTML and native executables are also 'export'; in a way it makes sense that it’s not 'save' because this is compiling to a format that can be distributed but not edited, so 'save' is for pure carts and 'export' for derived things.

Now on the command line, there is no option for saving, so all operationes use '-export', even though it can be used to create pure carts in P8PNG or P8ROM format that can be loaded and edited again!

P#97087 2021-09-09 00:31 ( Edited 2021-09-09 00:32)

Looking forward to the online hiscores feature. It will give a new lease of life to a lot of existing Pico-8 games.

P#97189 2021-09-11 10:04
:: merwok

@zep program crashes (segfaults) with Scrap Boy

SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x1b}

P#97513 2021-09-19 01:01

Hi to all.
I have an issue with this new version. the PRINT function works differently from previous version in handling '\n' character.
In previous version when PRINT encounter '\n' character the line start from the beginning of the previous, now allway starts from 0. I post this screenshot as example.

This works with 0.2.2c version but the same code give me this issue with 0.2.3.
Thanks to @zep for pico-8 that allways remain a great program :)

P#97545 2021-09-19 12:50 ( Edited 2021-09-19 12:53)
:: dw817

Yep, I found this version of Pico-8 does indeed NOT run some of my carts correctly as they ran before, @ViperSnake75.

Also if it's ideas people are after, I have several:


While a good number of these ideas have been read and implemented by @zep since my initial request of them 2-years ago, glad to be of service, there are still several I think are also good ideas still in the list not yet done.

Of course pinnacle to all of this would be the ability to compile your .P8 to native Android/cellphone format of APK or OPK as the case might be. Some of the competing Fantasy Consoles have this ability already so it is not an impossibility. Of course I would never leave Pico-8 and am always delighted to see each new version @zep produces.

P#97570 2021-09-20 01:28 ( Edited 2021-09-20 01:32)

I am so excited!

P#97578 2021-09-20 09:53

Nice! Relatively new to pico-8, so don't know about all of the bugs other people are talking about, but I'm excited to see what else @zep adds!

And yes, I've already been utilizing live token count to my benefit. Thanks!

P#97733 2021-09-24 00:07 ( Edited 2021-09-24 00:08)

[Please log in to post a comment]

Follow Lexaloffle:        
Generated 2021-09-25 09:39:56 | 0.066s | Q:46