Hey All! PICO-8 0.2.6b is up now up on lexaloffle, Humble, itch.io, and for PocketCHIP and web (Education Edition). Note: you'll need to update to 0.2.6b to play new carts and SFX snippets created in 0.2.6!
Inverted Draw Operations
Thanks to @p01 for nudging me about this one! Filled draw operations (circfill, ovalfill, rectfill) can now be drawn inside-out: every pixel outside the area is drawn instead of every inside pixel. This can be controlled in a way similar to setting the fill pattern per draw call: first poke(0x5f34,0x2)
to enable inverted draws, and then set bits 0x1800 in the colour argument. Here is a snippet to blank out everything except a circle in the middle (that changes size):
poke(0x5f34,0x2) circfill(64,64,50+cos(t()/4)*10,0 | 0x1800) |
And a short program that draws a tunnel:
function _draw() cls() poke(0x5f34,0x2) -- hold ❎ to skip fill cc = circfill if (btn(❎)) cc = circ for z=7,1,-1 do local sx = cos(z/15+t()/4) * 50 local sy = sin(z/15+t()/4) * 50 cc(64+sx/z,64+sy/z,64/z, 7+z | 0x1800) end end |
High Memory Video Mapping
Before 0.2.6, display memory and spritesheets could be mapped to each other (at 0x0000, and 0x6000). They can now also be mapped to one of the four high 2k sections at 0x8000, 0xa000, 0xc000, and 0xe000, as long as they don't overlap with the map mapping which takes precedence. There is a nominal cpu cost when a mapped region changes between graphics and map, but otherwise changing mappings is "free" apart from the poke() call overhead.
This was a previously rejected wishlist feature, but due to a bug discovered (and rightly abused!) by @StinkerB06, it seemed proper to offer this as a substitute before that bug is "fixed" in a future version. Well played!
Here's an example of moving the spritesheet to 0x8000 so that 0x0 can be used for something else. Just a reminder of a confusing gocha: remapping the spritesheet remaps the whole memory area 0x0..0x1fff. So once @0x5f54 is set to e.g. 0x80, even memory functions like memcpy, memset that operate on 0x0..0x1fff will be operate on 0x8000..0x9fff.
-- copy spritesheet to 0x8000 memcpy(0x8000,0x0,0x2000) -- clear spritesheet at 0x0 to prove it is no longer used! memset(0x0,0,0x2000) -- remap spritesheet to 0x8000 poke(0x5f54,0x80) -- draw something to prove it worked spr(1, 50,50) |
Waveform Instruments
Waveform instruments work roughly the same as SFX instruments: they each take up one SFX slot worth of data (SFX 0..7), and can be triggered from a regular SFX. But instead of treating the 64 bytes of note data as a regular SFX, they are used to represent 64 8-bit samples of a short looping waveform. Click on the new toggle button at the top right of the SFX editor to draw a waveform, and optionally pitch it an octave down with the "bass" toggle button. Waveform instruments can be used from inside SFX instruments, and also observe the detune, reverb and dampen filters.
Here are a couple of short demos (excuse the new WIP player -- it needs an initial tap to load it for browser compatibility). The first pattern shows some custom bass and lead instruments that are quite different from the built-in waveforms. Patterns 2&3 are more subtle, but those two instruments are also quite tonally different from any of the standard ones.
I think that doodling custom waveforms is great fun and opens up a new world of possibilities, but of course that in itself does set off alarm bells in terms of fantasy console design. I've come to view them as a worthwhile source of complexity that feels playful rather than overwhelming, and without creating a discontinuous jump in the "PICO-8 sound". Having said that, I'm sure I'll look back one day at earlier PICO-8 music with nostalgia for its particular simple charms. Here's a fitting tune by @ridgek to send off the old version!
Music Scale Snapping
A low-key (ha!) feature of PICO-8 since very early on is that holding CTRL while drawing frequencies snaps each note to the C minor pentatonic scale. This is useful for both sound effects and music -- you can't really go wrong walking up and down (or jumping around) those 5 notes.
In 0.2.6, the scale that is snapped to while holding CTRL can now be customized in the music editor. There is a toggle button at the bottom right to switch between volume and scale snapping. Click on the keyboard to toggle scale selection mode. There are two buttons for transposing (<<, >>), 3 preset scales, and an invert button to get 3 more:
Dim Diminished 7th // invert to get a whole-half scale Maj Major scale // invert to get pentatonic Who Whole tone scale // invert to get.. the other whole tone scale |
Changing the scale does nothing to alter the existing SFX -- it is applied only when holding CTRL and drawing frequencies.
A Little Music Theory
What is a scale anyway? Very roughly speaking, it is a selection of notes that are chosen to have a particular character or mood when used together. You might already be familiar with the scale formed by all of the white notes on a piano (or using keys qwertyu in PICO-8): C Major. Hit the Maj
preset button to select this scale, and hold down CTRL to doodle a sound (spd:1) or melody (spd:16) in frequency mode.
Inverting the major scale (hit Inv
) gives an Eb minor pentatonic scale, which is another name for all of the black notes. Try doodling some shapes again, and see how different that sounds. I think pentatonic scales are the most useful for starting out with melodies and sound effects, with its bright, resonant sound. To get from Eb minor pentatonic back to the default C minor pentatonic scale, hit <<
3 times to transpose down 3 semitones. Examples of major and pentatonic scales are given in the first 2 patterns:
The other two scale presets also have their own distinctive character, with examples above in patterns 2..4. Who
for a wholetone scale (every second semitone -- pattern 2), gives a floating ethereal feeling. Good for things like "falling down a hole" or "found a secret level". Dim
for a 4-note diminished 7th scale (every third semitone -- pattern 3) gives something more unresolved ("entering a hidden chamber", or "a boss appears"). Inverting the diminished scale gives the whole-half diminished which has an even more mysterious quality that is more like "that lever triggered something but we don't know what it is yet".
These are oversimplified and silly examples, but I hope it gives you an idea of the kind of things you can explore with scales! If you'd like to know more, I highly recommend @Gruber's tutorial series that has a lot of handy music theory weaved in and also @bikibird's interactive music theory tutorials.
Handheld Improvements
With the rise of handheld devices like the RGB30 and Miyoo Mini Plus, there are many more handheld users of PICO-8 now (welcome aboard!). 0.2.6 has a few adjustments to make life easier:
Metadata Mending
When favouriting a bbs cart in 0.2.5g using the typical RGB30 / MM+ configuration, it was showing up as a local file with no metadata (blue cart icon instead of orange). Not a huge problem, but those carts can not show their full title, author and lose the ability to auto-update and find similar carts.
0.2.6 fixes that bug, and also deals with those carts by pinging the bbs for metadata when they are opened. So to "mend" such a bbs cartridge that has a blue label in the favourites list, just open it once while wifi is enabled.
merge_joysticks
This is an option in config.txt, that treats the first n controllers as if they were a single merged controller. This is useful in situations where you want to use the built-in buttons on a handheld device, but then later plug in a controller (e.g. when you connect it to a TV), but want that controller to also be used for the same player. To set up PICO-8 for such a system, use merge_joysticks 2
in config.txt.
Shutdown from Options
You can now close PICO-8 from the options menu while playing a game. This is handy for devices that do not have a 'kill app' option / button combination. Previously it was necessary to first exit to splore, then open a cartridge menu and use the options menu from there.
Miscellaneous
Mac Universal Binaries
PICO-8 now ships with native support for Apple silicon, as well as intel versions bundled as a universal binary. The exporters produce executables in that same universal format. To do this, I had to bump the minimum required MacOS to 10.8. I know there are still a few of you out there using PICO-8 on older Macs that will otherwise become doorstops. I don't have a good solution for this yet, but later on I'll look at setting up a legacy build system for such machines if there is sufficient demand.
Menuitem Button Filtering
By default, pause menu items creating using menuitem() respond to any button press, including left and right. This is handy in some situations (toggle buttons) but annoying or dangerous in others (clear game data). menuitem() can now take a bit mask in the high bits of the first parameter, indicating which button presses to ignore. Bits 0x100 and 0x200 mean LEFT and RIGHT, so if you can ignore those button presses with:
menuitem(0x301, "option 1", my_callback) |
Improved Search
The search box in splore and on the bbs now returns more sensible results. Posts are sorted by number of stars, so if you type in "celeste", the first two results will be the original Celeste and Celeste 2. Imagine that! As a side-effect hack, you can search for " " and get an all-time highest starred cartridges list.
While working on search and scanning the BBS for preprocessor breakage, I made this collage of the 14 pages of featured cartridges that are now available (out of around 18k published carts). W00t! \o/
Preprocessor Removal
This is an internal change, but worth mentioning. 0.2.6 no longer uses a preprocessor at all (thanks to z8lua), so all of the code is running through a (modified) Lua 5.2 implementation as-is. Most of this happened in 0.2.5*, but there were a few leftover language features like short form print (using ?) and number parsing. 0.2.6 now also allows the use of "do" instead of "then" in if statements, which is something the preprocessor allowed (by accident!) and a number of early carts use it. There is a small amount of breakage of older carts that have things like unclosed or otherwise ill-formed comments that shouldn't be accepted. For those types of cases, I'm gradually working through older carts to make stealth fixes where needed. At this point the vast majority of existing carts should run as expected -- please do let me know if you see something weird that isn't a syntax error, which I can scan the BBS for automatically.
Socials
There are 2 new social usernames addable to your BBS profile: twitch.tv, and bluesky which is now open for signups without an invite. My social network of choice is still the fediverse / mastodon, but I think bluesky has the potential to coexist and be a nice place in the future ~ especially if they end up supporting gifs.
-> Add social handles to your profile
-> Find other lexaloffle users on bluesky / twitch
Changelog
That's all for now -- I'll catch you in a couple of weeks with a new machine!
Erm. Not sure why, but every time I click on the SFX editor button, Pico8 just hangs and then drops me back at the desktop :( Is there a logfile anywhere ?
I'm excited for the upper-memory sprite and video methods, this and the inverted draw functions are wonderful surprises! I'm so glad to be getting into PICO-8 at this time.
Thank you @zep! Looking forward to Picotron!
I was wondering if there was a way to make waveforms other than the mouse?
Yay! Really nice update, thx @zep
Guess I have a few updates to factor into the Cheat Sheet
(it's ok - nice problem to have!)
Thx again, as always 🤓 <3
I wondered why the search order had been shuffled around! While sorting by stars is a pretty good way of going through the standard search, IMO not so much for a by-author search; before the easiest way to see if someone you liked had made something new was to find a cart of theirs in your favorites, tap enter, scroll down and select the CARTS BY @zep
(or whoever), and PICO-8 would automatically search for BY:ZEP
, with the newest cart(s) on top. But now, it just shows their most popular work instead (odds are, you already know about it), with the newest one(s) likely being somewhere near the bottom (due to being more recent, and therefore having much less time to be starred). I would suggest that the old behavior should be restored when using a filter like BY:
or THREAD:
, reserving the star-sorting behavior for normal searches and the SIMILAR:
filter.
Been testing that out myself, if you center the circlefill at 64,64 and do radius 0 then there is a tiny dot in the middle. I found I had to do a if else statement to do cls() if r <= 0 to get it to completely wipe.
That tunnel looks familiar 👀
After playing with the waveform instruments for a few minutes, I can safely conclude that I have no idea what I'm doing
The upper memory thing seems like a good way to put layers in an art tool
Since there's changes being done to the search I have a suggestion about the web site.
When you link to a game from , for example discord, the preview displayed just says the name of the game. For people who are not used to seeing Pico 8 links, this link might look a bit like just a random link, rather than a link to a cool pixel game. It would be nice if the page's metadata would have at minimum the cartridge of the game.
Why include pentatonic minor though? Wouldn't it make more sense to pick a minor scale and then let people choose to use less of the notes, especially since you're including major anyway?
Has anyone else experienced crashes when hitting the SFX editor button ?
@Minion what environment are you running in, and what if any error messages are you seeing?
@kozm0naut its windows 10. and there is no message. I click on the SFX editor button and the mouse hangs for a short while then it just closes down. Not to worry tho, I've just gone back to the previous version which is stable.
I can't speak to zep's motives obviously but for whatever it's worth, I've seen/heard advice for people who want to be able to play around on the piano but don't necessarily want to learn to "play piano" to stick to improvising on only the black keys (AKA F# Major/D# Minor pentatonic.)
It's shockingly difficult to make something sound bad if you're sticking to a pentatonic scale which is not necessarily the case with the natural minor scale. Giving them mino and letting them choose fewer notes sort of requires they know which set of notes to choose. But not everyone who wants to try their hand at making a game will have a music theory background. A nice friendly, "just stick to these five notes and you'll be fine," can be the confidence boost someone needs to try making their own music.
Not everyone, even complete beginners, will either want or need that. But it's easier for people who already know what they're doing to diverge from the defaults and get good results. So pentatonic seems like a reasonable default to me at least. YMMV
Love these new features!
Please consider this for a future release: It's easier to write visualizers for PCM audio than it is for standard PICO-8 music because it's easy enough to get a byte that represents the current amplitude, but that's not possible with music/SFX. For example, writing an oscilloscope visualizer is pretty much impossible for music/SFX, but simple for PCM. Ideally, I'd like a stat that would return the current amplitude of the music/SFX as it is being played.
This could be a bug; observed on this latest version (MacOS build).
The code below draws a moving vertical line.
It runs smoothly (as in, line is drawn progressively towards screen edge) on 0.2.5g.
It does not (occasionally jumps back a few pixels before "resuming" at next expected position) on 0.2.6b.
Can anyone reproduce this ?
Thanks
x = 0 function _update60() x += 1 if x > 127 then x = 0 end end function _draw() cls(12) line(x,0,x,127,7) end |
EDIT : glitch sometimes only observed after a few sweeps ( 0 1 ... 128 0 1 ... 128 0 1 ... )
@alexr I'm not able to reproduce this unexpected behavior in 0.2.6b (on Linux via Chrome OS). Everything looks good here.
@kozm0naut Thanks. Strange. This could be a Mac specific issue. I'll test it on another machine.
Is it me or "merge_joysticks" is not working as intended? I've tried on Steam Deck (linux) and RGB30 (rPi) and instead of merging two or more physical controllers into a single virtual "joystick 0" it does the opposite: the inputs from the physical controller are being applied to virtual joysticks for Player1 and Player2 in Pico-8.
merge_joysticks 2 #not working? |
@GalaxyNova this post might have what you're looking for: https://www.lexaloffle.com/bbs/?tid=45247
[Please log in to post a comment]