More bugfixin'
PICO-8 0.2.5f 0.2.5g is up now up on lexaloffle, Humble, itch.io, and for PocketCHIP and web (Education Edition).
v0.2.5g Changelog:
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 Changelog:
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: 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
Nicely done, @zep. Get around to my other 1000+ previous suggestions and I'll be happy. :)
Seriously, fine job here. I'm very glad you are sticking with the project and solving problems as they arise.
bug report: ?(split"100hello,200")[1]
prints 100
instead of 100hello
-- this broke https://www.lexaloffle.com/bbs/?pid=125269#p
n b and x seem to behave differently from other letters inside split (checked with for a=0,25 do g=chr(97+a) print(g..": "..((split("100"..g))[1])) flip() end
)
I think that might be undefined behavior, since by default split()
will try to turn stuff into numbers if it can. I'm not sure what the threshold for "if it can" is, so that's why I'd say it's undefined behavior. If you only want strings, you'd need to do split("100hello,200",false)
to disable that feature.
That being said, I think it'd be reasonable for the behavior to be explicit that any substring that isn't entirely a number should remain a string. I imagine right now it's calling tonum() or something and, if it doesn't fail, it accepts it as a number, but tonum() can be permissive, iirc.
Okay yup I tested the current build vs. an old build and the issue isn't split(), it's tonum().
Previously, tonum("100hello") would return nothing, i.e. an empty tuple, not even "return nil". I assume it just hit a blank "return" statement or fell off of the end of the function. Now it returns 100 as a number.
Not sure what behavior is more desirable, but it's definitely not backwards-compatible at the moment.
(In my opinion "100hello" is a malformed number and should not silently convert to 100.)
@Felice Regardless of what the correct behaviour of tonum is I don't believe it to be the correct behaviour of split.
Also its really really wierd.
foreach(split( [[ 10 green bottles, hanging on the wall 100hello 100hello green 100green 1a 2b 3c 4d 5e 6f 7g 8h 9i 10j 11k ]],"\n" ), print) |
|100hello|100|
|100green|100green|
|2b|2b|
|3c|3|
As pointed out to me by a user on mastodon, the new update has broken a couple things in Into Ruins. Fire/Healing effects are persisting after they should be gone, and there's a random "1" showing up on the inventory screen instead of the "----stowed" separator.
Not sure if anything else is behaving differently. I haven't investigated yet but it might be related to the tonum/split changes mentioned above.
Thanks @pancelor -- quite a serious problem so I've patched it in 0.2.5g just now.
@ericb Almost certainly caused by the broken tonum() in 0.2.5f. I've confirmed that the random "1" is gone in 02.5g, but haven't checked the fire/healing effects yet.
@Felice yep, the original behaviour is definitely the desirable one (and in any case should be backwards compatible).
tonum() is meant to accept whitespace after the number (it is still considered well-formed) but not random identifier junk. This is different from the tokenizer, which allows e.g. "a=3b=3", and I conflated the two while working on removing remains of the preprocessor.
EDIT: wrote this before @zep's comment above. Thanks for fixing it! Excited to finally get the new version on my handheld.
Okay yeah it is definitely more split problems.
The first string that's breaking is "\n\f1 ………………… STOWED"
: this one is very weird because it seems like just because of the "1" following the \f control character, the whole string gets converted to "1" by tonum(). This split happens in a generic CALL() function that needs to handle numbers as well as strings. CALL() just parses function names/parameters from a string and calls them to save tokens. The line call"listitems(t,t)print(\n\f1 ………………… STOWED)listitems("
contains the offending string. Here's the CALL() function:
function call(str) for i,s in inext,split(str,")")do local func,args=unpack(split(s,"(",false)) _ENV[func](usplit(args)) end end function usplit(str,delim) return unpack(split(str,delim)) end |
Usplit is where the errant split happens, though I'm a little confused as to why the first call to split() in call() isn't reading the whole "print(\n\f1 ………………… STOWED" string as "1", since it also contains "1" within it. Strange stuff going on here. In any case it's easy to fix by just switching to calling print() with a color instead of using the control charactrer (changing the line to call"listitems(t,t)print(\n ………………… STOWED,1)listitems("
).
The second problem (fire/healing effects persisting) was a bit harder to track down. The animations in the game are stored as strings where each character represents either a frame as a number, or a special function to call. The animation "firedeath" is used for both the fire and healing effects, and it has the string "20o"
. Here again, split() is reading it as just 20, and the "o" is getting dropped, which happens to call the DESTROY() function, hence these effects persisting after their death animation plays. This is also pretty easy to fix by adding an "n" to the start of the animation which is essentially a no-op, and makes the string no longer get read as a number. On the plus side, tracking this down made me find other animations like the player walk animation that were already being played with incorrect timing because they had eg. leading zeroes that were being ignored when getting parsed in.
@ericb
Oof, that's quite an interesting journey -- sorry about that! I'm glad you could confirm they were both caused by the same change.
Hey zep, I'm sorry if this was already reported, but it seems like this update has caused one of my games to stop functioning on the BBS specifically. It returns a token limit error. According to the folks on the PICO-8 Discord server, this might be caused by the usage of [[]]
nesting. You might want to scan the BBS to see if this update has caused any other games to break !
Shouldn't the web player (barring security issues) keep playing at the version that the cart was uploaded at? Yes this still breaks splore.
Shouldn't the web player also prevent you uploading a cart that is in too old a version?
That's how I would have assumed this should work.
Oh, hey @JTE! Indeed, and thanks for updating the BBS cart.
@Yolwoocle Oh no, not bird with guns! I've made a stealth patch just now (birdswithguns-4) that removes the nested comment and golfs back some tokens so that it will fit: I changed trainpal[]
to be flat array, and changed some split("")
statements to split""
(Lua can take a string or table literal as a single parameter without the () ).
The reason for recent breakages is that the runtime will be frozen (forever?) soonish, so I'm working on reducing maintenance and compatibility issues in the future, which has sometimes required large internal changes (most notably, removing a pre-processor pass that used to be responsible for most of PICO-8's modifications to Lua syntax).
I hope to not leave any carts behind though, right back to those authored in 2015 -- please anyone feel free to mention any discovered broken carts here, and I'll either fix the runtime (most desirable), or patch the cart itself (plan B when the cart is doing something that can no longer be supported).
> Shouldn't the web player (barring security issues) keep playing at the version that the cart was uploaded at?
@SquidLight That would solve the immediate problem, but be a giant headache to support. I'd rather focus on improving a single standard runtime, even if it means that 1% of carts are temporarily broken 1% of the time.
> Shouldn't the web player also prevent you uploading a cart that is in too old a version?
@SquidLight I think a warning upon upload would suffice instead of totally barring it, in most cases the code the cart contains would work on newer versions
@zep now that comments are the same as standard lua, is there any reason to have the preprocessor remove them?
as a bit of motivation, here's another infinite token exploit, which (ab)uses this quirk ;)
a=[--[[]][ [=[ ]] print(123) |
([--[[]][
turns into [[
after preprocessing which opens a long string)
now just to find an exploit using ?
, and the preprocessor can be ditched entirely right? (and on a more serious note, is there any reason that it's still preprocessed?)
@Yolwoocle np!
> now that comments are the same as standard lua, is there any reason to have the preprocessor remove them?
@gonengazit Right -- in a not-so-distant update the comments will be kept intact (and // counted as -- inside the Lua implementation). While I'm aiming to remove the preprocessor entirely (hence the move to go with standard Lua long-form comments), I'm doing it step by step so there will be some funky exploits possible in the intermediate stages :p
At the moment the preprocessor is only handling comments (I guess it didn't need to in 0.2.5g), short-form ? print(), and number parsing.
This is not specific to this version, since I updated from 0.2.5c to this one in hopes that it would fix this, but I figure I should put it here nonetheless.
Regardless of whether the game is running with Ctrl+R, or is an exported .EXE, if I try to drag a .TXT file and drop it onto the game window, it instantly crashes.
Nothing is logged to the console, and others don't seem to be able to reproduce it.
On my end, it's as simple as writing:
function _draw() cls() end |
...then Ctrl+R, followed by dropping this text file:
0,32,32 0,40,40 0,44,44 |
In addition, dropping a .PNG file and checking it with stat(121) always returns false. Not sure if it's related, but since they're so close to eachother and so similar in function, might as well mention it too.
@zep Oops, seems like you messed up something while fixing Birds With Guns. I didn't check after you made the modification, but the color of the first wagon is supposed to be red, not green (the second wagon is supposed to be green, etc). That's okay; I'll fix it myself, just wanted to point that out haha !
Sorry if this has been covered already. At the map editor, I think the hex sprite number is not working. When I press 'H' nothing happens.
Here is what I was expecting, what was happening before 0.2.5g
@roroyobert because h conflicted with flipping sprites it was moved to cntrl+h instead
not sure if this is a bug or if I'm just misinterpreting the help, but when you do "help pset" or "help pget" it shows the correct help text but pulls up the functions and args of sget/sset.
[Please log in to post a comment]