Hi,
on a Mac (Big Sur) I did some experiments with drawing a 3D starfield using lines.
However, PICO-8 regularly crashes completely (play around with the 6 buttons for the star speed in all 3 directions) and a debug with lldb on the Mac terminal uncovered the following:
So there seems to be a problem in 0.2.2 with line drawing somewhere.
I hope this can be fixed for the upcoming 0.2.2b
- Martin
After doing quite a bit of testing, I've pinpointed what I believe are the minimal conditions that need to be true to trigger the crash.
When executing the command line(x1,y1,x2,y2), the following conditions must be true for a crash to occur (the same thing happens if y1 and y2 are exchanged, but for the sake of simplicity, y1 is assumed to be positive here):
- flr(x1)!=flr(x2)
- y1>=0 and y1<128
- flr(y2-y1)==0x8000
- flr(y2)<0x8080
I've prepared a demonstration cart which, in v0.2.2, should crash almost immediately. It tries to draw lines using the values for y and i in the code, and it also displays two of the aforementioned conditions. It consistently crashes the moment both conditions display true.
y=0x8000 for i=128,0,-0x0000.0001 do cls() print(" i = "..tostr(i,true)) print(" y = "..tostr(y,true)) print(" y+i = "..tostr(y+i,true)) print() print(" flr(y)==0x8000 = "..tostr(flr(y)==0x8000)) print("flr(y+i)<0x8080 = "..tostr(flr(y+i)<0x8080)) flip() line(0,i,1,y+i) end |
The line() command with large-magnitude negative numbers appears to behave strangely in general; I don't remember what arguments triggered it exactly, but one line command I tried while pinpointing the bug filled almost the entire screen up with pixels, which shouldn't happen with a single line! I hope zep can fix this for v0.2.2b just as much as you do.
EDIT: Oh my, the web export behaves strangely! It seems that the text for the pause menu becomes jumbled after the crash conditions happen, instead of the PICO-8 player just crashing outright...and then when I reset the cart, it gives me a "syntax error: ) expected" message and a "attempt to call a nil value" message at the same time, after which I can't do anything. Curiouser and curiouser...
Thanks @leissler, @JWinslow23 -- this is fixed for 0.2.2b
It was happening when ABS(dy1-dy0) >= 32768, causing some int32's to overflow during clipping calculations (I've been trying to remove int64's where possible because they are very slow under asm.js). In 0.2.2 the low-level putpixel doesn't do any range checking, so when the clipping is incorrect it means arbitrary memory can be clobbered, which seems to produce the weirdest behaviour under the web version.
I just installed 0.2.2c and it's much more stable now.
However, I still get PICO-8 to crash if I let the stars go fast enough and play around with insane speeds.
lldb says the following:
I don't think it's too critical anymore, but just good to know that there is still a vulnerability in the line drawing code somewhere.
The latest code I used is this
st={} pst={} stc={7,6,13,5} o=count(stc) zd=256 ns=250 sx,sy,sz=0,0,-2 function _init() xd=64*zd yd=64*zd srand(0x0000.72f5) for i=0,ns-1 do st[3*i]=rnd(2*xd)-xd st[3*i+1]=rnd(2*yd)-yd st[3*i+2]=rnd(zd) end end function getinput() if (btn(0)) sx-=10 if (btn(1)) sx+=10 if (btn(2)) sy-=10 if (btn(3)) sy+=10 if (btn(4)) sz-=0.2 if (btn(5)) sz+=0.2 end function _update60() getinput() for i=0,ns-1 do x,y,z=st[3*i],st[3*i+1],st[3*i+2] px,py,pz=x,y,z x+=sx y+=sy z+=sz if x>xd then x-=2*xd px=x py=y pz=z elseif x<-xd then x+=2*xd px=x py=y pz=z end if y>yd then y-=2*yd px=x py=y pz=z elseif y<-yd then y+=2*yd px=x py=y pz=z end if z<0 then z+=zd px=x py=y pz=z elseif z>zd then z-=zd px=x py=y pz=z end st[3*i],st[3*i+1],st[3*i+2]=x,y,z pst[3*i],pst[3*i+1],pst[3*i+2]=px,py,pz end end function _draw() cls(0) print(stat(1),0,0,14) for i=0,ns-1 do x,y,z=st[3*i],st[3*i+1],st[3*i+2] px,py,pz=pst[3*i],pst[3*i+1],pst[3*i+2] line(px/pz+64,py/pz+64,x/z+64,y/z+64,stc[1+flr(o*z/zd)]) end end |
on web - it shows memory corruption artifacts, see ‘garbage lines’ on top.
Hah, like the good ol' Amiga times, when we had the "normal" crashes (called guru meditation, where the processor exception was handled) and then we had "freak-outs", which were totally unpredictable memory overwriting monsters with spectacular effects when chip-memory was randomly filled... good stuff ;)
The only hint I have here is that when I change the clipping plane from 0 to 1 or 2 then it gets significantly harder to crash it.
So instead of having this in the update()
if z<0 then z+=zd px=x py=y pz=z |
writing
if z<2 then z+=zd px=x py=y pz=z |
Since we are dividing by z, this would suggest that it's still about significantly large coordinates for the lines.
[Please log in to post a comment]